Angular13中ng-select的change/ngModelChange触发emit报错问题
问题原因与解决方案
核心问题:变量名冲突
你遇到的错误根源是组件内的@Output变量名与ngModel绑定的变量名重复:
- 你定义了
@Output() planSelected: EventEmitter<PlanWithImage> - 同时在
ng-select上用了[(ngModel)]="planSelected"
Angular的双向绑定语法[(ngModel)]会在组件内创建一个同名属性(或覆盖已有的同名属性),导致原本的EventEmitter被替换成PlanWithImage类型的普通变量,自然就没有emit方法了。而通过(click)调用时不会触发这个覆盖逻辑,所以能正常工作。
修复方案
把ngModel绑定的变量改成组件内已有的selectedPlan(避免和@Output的planSelected重名),调整后的代码如下:
修改后的HTML代码
<div class="dropdown-with-add-button"> <ng-select class="custom-ng-select" notFoundText="{{ 'labelNoResultAfterResearch' | translate }}" id="dropdown-list-groups" [clearable]="false" [(ngModel)]="selectedPlan" (change)="selectPlan()" > <ng-container *ngIf="plansSidebar"> <ng-option *ngFor="let plan of plansSidebar.plans"> <div class="plan-container"> <div class="image-container"> <img class="plan-item-image" src="{{ plan.imageChaine }}" /> </div> <div class="text-container"> <p class="plan-item-libelle">{{ plan.libelle }}</p> </div> </div> </ng-option> </ng-container> </ng-select> </div>
组件TS代码无需修改
组件内已经存在selectedPlan变量,且selectPlan方法中emit的就是该变量,保持原有逻辑即可:
export class PlanChildComponent implements OnInit { _plansSidebar: PlansSidebar; get plansSidebar(): PlansSidebar { return this._plansSidebar; } @Input() set plansSidebar(value: PlansSidebar) { if (value) { this._plansSidebar = value; this._plansSidebar.plans.sort( (x, y) => x.ordreAffichage - y.ordreAffichage ); if (this._plansSidebar.plans.length > 0) { this.selectedPlan = this._plansSidebar.plans[0]; } } } @Input() idSelectedPlan: number; @Input() loading: boolean; @Output() planSelected: EventEmitter<PlanWithImage> = new EventEmitter<PlanWithImage>(); selectedPlan: PlanWithImage; constructor() {} ngOnInit(): void {} public selectPlan() { this.planSelected.emit(this.selectedPlan); } }
额外建议
后续定义@Output时,建议使用带有动作前缀的命名(比如planSelectedChange),既符合Angular双向绑定的规范,也能从根源上避免这类变量名冲突问题。
内容的提问来源于stack exchange,提问作者QToche
相关产品推荐
相关产品推荐

