Angular 15子组件无法向父组件emit字符串问题排查
Angular 15子组件向父组件传值失效问题解决
问题场景
在Angular 15项目中,尝试从子组件filters.component.ts向父组件home.component.ts传递字符串。此前在其他组件实现过相同逻辑,但使用*ngFor遍历字符串数组并传递category字符串到方法时出现异常:点击按钮触发事件后,父组件home.component.ts中的onShowCategory()方法未执行(添加console.log无输出),页面也无法显示选中的category值。
相关代码
filters.component.html
<mat-expansion-panel *ngIf="categories"> <mat-expansion-panel-header> <mat-panel-title>CATEGORIES</mat-panel-title> </mat-expansion-panel-header> <mat-selection-list [multiple]="false"> <mat-list-option *ngFor="let category of categories" [value]="category"> <button (click)="onShowCategory(category)">{{ category }}</button> </mat-list-option> </mat-selection-list> </mat-expansion-panel>
filters.component.ts
import { Component, EventEmitter, Output } from '@angular/core'; @Component({ selector: 'app-filters', templateUrl: './filters.component.html', styleUrls: [] }) export class FiltersComponent { @Output() showCategory = new EventEmitter<string>() categories: string[] = ['shoes', 'sports']; onShowCategory(category: string): void { this.showCategory.emit(category); } }
home.component.html
<mat-drawer-container [autosize]="true" class="min-h-full max-w-7xl mx-auto border-x"> <mat-drawer mode="side" class="p-6" opened> <app-filters (showCategory)="onShowCategory($event)"></app-filters> </mat-drawer> <mat-drawer-content class="p-6"> <app-products-header (columnsCountChange)="onColumnsCountChange($event)"></app-products-header> {{ category }} <!-- 选中后应显示的category --> </mat-drawer-content> </mat-drawer-container>
home.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'app-home', templateUrl: './home.component.html', styleUrls: [] }) export class HomeComponent { cols = 3; category: string | undefined; onColumnsCountChange(colsNumber: number): void { this.cols = colsNumber } onShowCategory(newCategory: string): void { this.category = newCategory; } }
问题根源
问题出在mat-list-option的默认行为上:当点击它内部的按钮时,mat-list-option会优先触发自身的选中逻辑,并且自动阻止了按钮点击事件的冒泡传递,导致你绑定的(click)事件根本无法触发,自然也就不会执行onShowCategory方法和发射事件。
解决方案
方案1:阻止按钮事件冒泡
直接修改按钮的点击绑定,添加$event.stopPropagation()来阻止事件向上传递给mat-list-option:
<button (click)="onShowCategory(category); $event.stopPropagation()">{{ category }}</button>
方案2:使用mat-selection-list自带的选中事件(推荐)
既然用了Material的选择列表组件,直接利用它原生的selectionChange事件更符合组件设计逻辑,还能去掉多余的按钮:
- 修改filters.component.html:
<mat-selection-list [multiple]="false" (selectionChange)="onCategorySelected($event)"> <mat-list-option *ngFor="let category of categories" [value]="category"> {{ category }} </mat-list-option> </mat-selection-list>
- 修改filters.component.ts的方法(记得导入对应的类型):
import { MatSelectionListChange } from '@angular/material/list'; // ... onCategorySelected(event: MatSelectionListChange): void { this.showCategory.emit(event.option.value); }
方案3:移除mat-list-option(若不需要选择高亮特性)
如果不需要Material选择列表的选中高亮等特性,直接用普通列表包裹按钮即可:
<ul> <li *ngFor="let category of categories"> <button (click)="onShowCategory(category)">{{ category }}</button> </li> </ul>
验证
采用任意一种方案后,点击分类选项时,父组件的onShowCategory方法会正常执行,页面也能正确显示选中的category值。
内容的提问来源于stack exchange,提问作者Xander Juneau
相关产品推荐
相关产品推荐

