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

Angular 12 mat-select选项渲染正常但无法选中问题求助

Angular 12.1 mat-select点击选项无响应排查

问题概况

  • 基于Angular 12.1开发表单组件,使用Angular Material的<mat-select>控件
  • 通过服务异步获取数据,用*ngFor渲染<mat-option>选项,选项显示正常,但点击后无任何反应
  • 表单因该必填项为空始终处于无效状态
  • 已尝试异步数据加载、移除翻译服务、改用formGroup等方法,问题未解决

相关代码

component.html

<div class="row">
    <div class="col-md-10">
        <h2>{{ "general.add" | translate }} {{ "general.distributionCenter" | translate }}</h2>
    </div>
</div>
<div class="row">
    <form #form class="form col-md-10" fxLayout="column" fxLayoutAlign="center center" (ngSubmit)="onSubmit(form)">
        <div class="row">
            <div class="col-md-4">
                <mat-form-field appearance="outline" class="w-100">
                    <mat-label>{{ "distributionCenters.name" | translate }}</mat-label>
                    <input matInput [(ngModel)]="dc.name" name="name" #name="ngModel" required>
                </mat-form-field>
            </div>
            <div class="col-md-4" *ngIf="countriesReady === true">
                <mat-form-field appearance="outline" class="w-100">
                    <mat-label>{{ "general.country" | translate }}</mat-label>
                    <mat-select [(ngModel)]="selectedCountry" name="selectedCountry" required>
                      <mat-option *ngFor="let country of countries" [value]="country.value">
                        {{ 'countries.' + country.displayValue | translate }}
                      </mat-option>
                    </mat-select>
                  </mat-form-field>                  
            </div>
        </div>
    </form>
    <div class="col-md-2">
        <button type="submit" mat-raised-button class="w-100" color="primary">{{ "general.add" | translate }}</button>
    </div>
</div>

component.ts

import { AfterViewInit, Component, OnInit } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { DistributionCenter } from 'src/app/interfaces/distribution-center';
import { ParamService } from 'src/app/services/params.service';

@Component({
  selector: 'app-create-distribution-center',
  templateUrl: './create-distribution-center.component.html',
  styleUrls: ['./create-distribution-center.component.scss']
})
export class CreateDistributionCenterComponent implements OnInit, AfterViewInit {

  countries: any;
  regions: any;
  communes: any;
  companies: any;

  dc: DistributionCenter = {
    name: '',
    address: '',
    regionId: '',
    communeId: '',
    companyId: '',
    latitude: 0,
    longitude: 0
  }

  selectedCountry: any;
  countriesReady: boolean = false;
  countriesArray: { value: string; displayValue: string; }[] = [];

  constructor(
    private translate: TranslateService,
    private paramService: ParamService
  ) {
    this.selectedCountry = null;
  }

  ngOnInit(): void {
    this.getCountries();
    console.log(this.countries);
  }

  ngAfterViewInit(): void {
    this.getCountries();
    console.log(this.countries);
  }

  onSubmit(form: any): void{
    console.log(form.value);
    /* some logic */
  }

  getCountries(){
    this.paramService.getParams("country").subscribe((res: any) => {
      this.countries = res.params;
      this.countries.forEach(((c: any) => {
        this.countriesArray.push({
          value: c._id,
          displayValue: c.config.name.toLowerCase()
        })
      }));
      this.countriesReady = true;
    })
  }

  getTranslation = (param: string) => {
    return this.translate.instant(`countries.${param.toLowerCase()}`);
  }
}

问题排查及解决方案

1. 数据源绑定错误

模板中*ngFor遍历的是原始的countries对象,但你在订阅回调里把处理好的value/displayValue数据存入了countriesArray,原始countries中并不存在这两个属性,导致[value]="country.value"绑定的是undefined,点击选项时无法正确赋值给selectedCountry。

修复:模板中改为遍历处理后的countriesArray:

<mat-option *ngFor="let country of countriesArray" [value]="country.value">
  {{ 'countries.' + country.displayValue | translate }}
</mat-option>

2. 重复调用数据接口

ngOnInit和ngAfterViewInit中都调用了getCountries(),导致两次请求数据,countriesArray被重复填充,可能引发渲染异常。

修复:移除ngAfterViewInit中的getCountries()调用,只保留ngOnInit中的一次调用:

ngAfterViewInit(): void {
  // 移除this.getCountries();
  console.log(this.countries);
}

额外优化建议

  • 将selectedCountry初始值设为''而非null,避免与表单必填校验的初始状态冲突
  • 添加trackBy函数优化*ngFor渲染性能:
<mat-option *ngFor="let country of countriesArray; trackBy: trackById" [value]="country.value">
  {{ 'countries.' + country.displayValue | translate }}
</mat-option>

在component.ts中添加:

trackById(index: number, item: any): string {
  return item.value;
}

内容的提问来源于stack exchange,提问作者Nicolás Acevedo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 21:38:09