如何实现支持单选的mat-card列表组件并向父组件传递选中项标识
Angular 单选卡片列表组件实现方案
你提到用到mat-card,默认基于Angular + Angular Material技术栈实现,步骤如下:
核心逻辑
选中状态统一托管给列表容器组件,单选切换逻辑由容器处理,对外暴露选中ID供父组件读取,每个卡片仅负责接收选中状态、触发选择事件。
分步实现
1. 定义可选中卡片组件(可选,也可直接用原生mat-card)
如果需要统一卡片的选中样式和交互,先封装通用子组件selectable-card:
组件TS代码
import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-selectable-card', templateUrl: './selectable-card.component.html', styleUrls: ['./selectable-card.component.css'] }) export class SelectableCardComponent { // 卡片唯一标识,用业务ID即可 @Input() itemId: string | number; // 接收当前是否选中的状态 @Input() isSelected: boolean; // 点击时向外抛出选中的ID @Output() selectCard = new EventEmitter<string | number>(); }
组件模板代码
<mat-card [class.selected]="isSelected" (click)="selectCard.emit(itemId)" > <!-- 插槽,支持自定义卡片内容 --> <ng-content></ng-content> </mat-card>
组件样式代码
mat-card { cursor: pointer; transition: all 0.2s ease; margin-bottom: 12px; } /* 选中状态样式,可自行调整 */ mat-card.selected { background-color: #e0f2fe; border: 2px solid #0284c7; box-shadow: 0 4px 12px rgba(2, 132, 199, 0.15); }
2. 实现卡片列表容器组件
封装列表组件统一处理单选逻辑:
组件TS代码
import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-card-list', templateUrl: './card-list.component.html', styleUrls: ['./card-list.component.css'] }) export class CardListComponent { // 当前选中的ID,支持双向绑定 @Input() selectedId: string | number | null = null; @Output() selectedIdChange = new EventEmitter<string | number>(); // 处理卡片选中事件 handleCardSelect(id: string | number) { // 单选逻辑:直接替换当前选中ID this.selectedId = id; this.selectedIdChange.emit(id); } }
组件模板代码
<div class="card-list"> <!-- 插槽,支持放入任意数量的卡片 --> <ng-content></ng-content> </div>
3. 父组件中调用
父组件可以直接读取、绑定选中的ID:
父组件TS代码
// 定义你的卡片列表数据 cardList = [ {id: 1, title: '卡片1', content: '卡片1内容'}, {id: 2, title: '卡片2', content: '卡片2内容'}, {id: 3, title: '卡片3', content: '卡片3内容'}, ] // 绑定当前选中ID currentSelectedId: number | null = null;
父组件模板代码
<!-- 用双向绑定直接拿到选中值 --> <app-card-list [(selectedId)]="currentSelectedId"> <!-- 循环渲染卡片 --> <app-selectable-card *ngFor="let card of cardList" [itemId]="card.id" [isSelected]="currentSelectedId === card.id" (selectCard)="$event && handleCardSelect($event)" > <!-- 自定义卡片内容 --> <mat-card-header> <mat-card-title>{{card.title}}</mat-card-title> </mat-card-header> <mat-card-content> <p>{{card.content}}</p> </mat-card-content> </app-selectable-card> </app-card-list> <p>当前选中的卡片ID:{{currentSelectedId}}</p>
更优简化实现
如果不想封装太多组件,可以直接用Angular CDK自带的SelectionModel实现单选逻辑,代码量更少,稳定性更高:
- 导入依赖:
import { SelectionModel } from '@angular/cdk/collections'; - 初始化单选实例:
selection = new SelectionModel<number>(false, []);第一个参数false代表单选模式 - 模板中直接绑定状态:
<mat-card *ngFor="let card of cardList" [class.selected]="selection.isSelected(card.id)" (click)="selection.select(card.id)" > <!-- 卡片内容 --> </mat-card> <p>当前选中的ID:{{selection.selected[0]}}</p>
选中样式和之前的实现一致,不需要额外写单选切换逻辑,CDK已经内置了所有选中、取消选中的处理。
内容的提问来源于stack exchange,提问作者Awybin
相关产品推荐
相关产品推荐

