You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 11:01:25