【问题标题】:How to show a default value in a mat-select of a dynamic form?如何在动态表单的 mat-select 中显示默认值?
【发布时间】:2022-08-13 20:31:56
【问题描述】:

我正在使用 Angular 材料将项目更新到 Angular 14,我已经生成了一个包含多个字段的通用表单,但 mat-select 不保留默认选项。

我正在从 component.ts 生成动态 FormControl,如果显示了值,则为文本字段,但 mat-select 不是。

这是我的component.html:

<div  [formGroup]=\"formDialog\" mat-dialog-content *ngFor=\"let column of data.columns\">
    <mat-form-field *ngIf=\"column != \'province\'\">
        <input matInput [formControlName]=\"column\" [placeholder]=\"column\">
    </mat-form-field>
    <mat-form-field *ngIf=\"column == \'province\'\">
        <mat-label>{{ column }}</mat-label>
        <mat-select [formControlName]=\"column\" (valueChange)=\"currProvince($event)\"> 
            <mat-option *ngFor=\"let item of geoProvinces\" [value]=\"item\">
                {{ item.nm }}
            </mat-option>
        </mat-select>
    </mat-form-field>
</div>

这是我的component.ts:

////////////
this.data.dataRow = {
   \"name\":\"test3Prov\",
   \"phoneNumber\":123456,
   \"province\":\"Madrid\"
}
//////////////

ngOnInit(): void {

    this.getGeoAPI();

    let fieldControls = {};
    Object.entries(this.data.dataRow).forEach(([key, value]) => {
        fieldControls[key] = new FormControl(value || \'\');
    })
    this.formDialog = new FormGroup(fieldControls)
}

这是获得省份的方法:

getGeoAPI(): void {
    this.genericService.getPath(\'geoApi\').subscribe((elem: any) => {
      this.geoProvinces = elem.provinces
    })
  }

这是this.geoProvinces 的示例:

[
   {
      \"id\":\"01\",
      \"nm\":\"Álava\"
   },
   {
      \"id\":\"02\",
      \"nm\":\"Albacete\"
   },
   {
      \"id\":\"03\",
      \"nm\":\"Alicante\"
   }
]

这是显示形式的屏幕截图:

  • 省只是一个简单的字符串还是一个对象?从您的 TS 看起来它是一个字符串,从您的 HTML 看起来它是一个对象。
  • 对不起昨天我不得不离开!来吧,我发了一个问题来帮助你! :)
  • @manjirosano 此组件是在编辑表格行时显示的对话框。 this.data.dataRow是要编辑的行的对象,这里province是一个String,geoProvinces是存储省份列表的对象。我想要的是默认选择dataRow的省,虽然我可以改变它
  • @build我最终理解了它!我更新了我的答案,看看吧! :D

标签: angular angular-material angular-forms


【解决方案1】:

如果您最初为您的formControlName 赋予了一个值,那么您不需要做任何这些,我相信它应该显示它。
尝试将[formControlName]='column' 更改为[formControlName]='province',这应该可以工作,因为您已经在.ts 文件中给了它一个值!

并且不要使用valueChange() 使用selectionChange()!

【讨论】:

  • 我投反对票是因为每次您在 mat-select formControlName 和 [value] 或 [(value)] 中使用时,都会有一只小猫死去。答案是赋予 formControl 价值。注意:不要使用 (valueChange) 否则 (selectionChange)
  • 我删除了对你的这条评论的回答,但我认为它仍然是正确的。我以为我在说傻话,但不是真的,他总是可以改变selectedValue,selectionChange()的值,但我仍然理解你的观点,你是对的!拥有 formControlName 和 value 是愚蠢的,请原谅我的回答 xD
  • 真的我讨厌投反对票,但我不记得我纠正了这个“错误”多少次(但没有什么是愚蠢的,这是一个常见的错误)。我只是删除了反对票
  • @Eliseo 我应该投反对票,我会尽快纠正我的答案,感谢您的纠正! :)
  • 确实,省份的值是从我在表格中看到的内容中收集的。但仍然改变你所说的我无法显示默认值。我也尝试了以下方法,但它不起作用:this.formDialog.get('province').setValue(fieldControls['province'].value)
【解决方案2】:

问题是您的 mat-select 是一个对象数组,而您的 formControl 值是一个字符串

我想你可以在你的 mat-select 中使用值“item.nm”(或者你在你的数组中拥有的任何属性)

<mat-option *ngFor="let item of geoProvinces" [value]="item.nm">
      {{ item.nm }}
</mat-option>

顺便说一句,如果我们可以存储我们应该在选项 [ngValue] 而不是 [value] 中使用的对象

另一个选择是你真的想在 formControl 中存储“对象”,在这种情况下你可以添加你的 ngOnInit

Object.entries(this.data.dataRow).forEach(([key, value]) => {
     ...
})

this.formDialog = new FormGroup(fieldControls
const control=this.formDialog.get('province')
if (control && control.value)
{
   const province=this.geoProvinces.find(x=>x.nm==control.value)
   control.setValue(province?province:null)
}

更新

  //The array geoProvince is in the way 
     [{"id":"01","nm":"Álava"} ..]
  //And our data in the way 
     {"name":"test3Prov",
      "phoneNumber":123456,
      "province":"Madrid"
     }

所以首先我们需要考虑一下我们可以在 FormControl “省”中存储什么

我们可以存储“省名”

const fieldControls: any = {};
Object.entries(this.data.dataRow).forEach(([key, value]) => {
    fieldControls[key] = new FormControl(value || '');
})
this.formDialog = new FormGroup(fieldControls)

//the ng-select like -see mat-option [value]="item.nm"
<mat-select [formControlName]="column"(selectionChange)="currProvince($event)"> 
        <mat-option *ngFor="let item of geoProvinces" 
             [value]="item.nm">
            {{ item.nm }}
        </mat-option>
    </mat-select>

我们可以存储省份的“id”

const fieldControls: any = {};
Object.entries(this.data.dataRow).forEach(([key, value]) => {
    //we check if we are creating the formControl province
    //if true we asing the "id"
    if (key=="province"){
      const prov=this.geoProvinces.find(x=>x.nm==value)
      fieldControls[key] = new FormControl(prov?prov.id:null || '');
    }
    else
       fieldControls[key] = new FormControl(value || '');
})
this.formDialog = new FormGroup(fieldControls)

//the ng-select like -see mat-option [value]="item.id"
<mat-select [formControlName]="column"(selectionChange)="currProvince($event)"> 
        <mat-option *ngFor="let item of geoProvinces" 
             [value]="item.id">
            {{ item.nm }}
        </mat-option>
    </mat-select>

我们可以存储整个对象。我们需要考虑如果我们存储一个对象或者我们分配对象(在数组 geoProvinces 中搜索)或者我们使用属性“compareWith”

将整个对象搜索存储在数组 geoProvinces 中

const fieldControls: any = {};
Object.entries(this.data.dataRow).forEach(([key, value]) => {
    //we check if we are creating the formControl province
    //if true we asing the element
    if (key=="province"){
      const prov=this.geoProvinces.find(x=>x.nm==value)
      fieldControls[key] = new FormControl(prov?prov:null || '');
    }
    else
       fieldControls[key] = new FormControl(value || '');
})
this.formDialog = new FormGroup(fieldControls)

//the ng-select like -see mat-option [value]="item"
<mat-select [formControlName]="column"(selectionChange)="currProvince($event)"> 
        <mat-option *ngFor="let item of geoProvinces" 
             [value]="item">
            {{ item.nm }}
        </mat-option>
    </mat-select>

使用“比较”

const fieldControls: any = {};
Object.entries(this.data.dataRow).forEach(([key, value]) => {
    if (key=="province"){ //create "on-fly" and object"
       fieldControls[key] = new FormControl({nm:value} || '');
    else
      fieldControls[key] = new FormControl(value || '');
})
this.formDialog = new FormGroup(fieldControls)

//the ng-select like -see mat-option [value]="item"

//see also the [compareWith]="compareProvince"
<mat-select [formControlName]="column"
        [compareWith]="compareProvince"
        (selectionChange)="currProvince($event)"> 
        <mat-option *ngFor="let item of geoProvinces" 
             [value]="item">
            {{ item.nm }}
        </mat-option>
    </mat-select>

//and we declare compareProvince in .ts
compareProvince = (a: any, b: any) => a.nm == b.nm;

见stackblitz

【讨论】:

  • 我无法通过geoProvinces 对象过滤它在另一个方法中填充,在onInit 中该对象为空。无论如何,如果它获得了价值,我正在执行以下操作,但它不起作用:this.formDialog.get('province').setValue(fieldControls['province'].value)
  • 你的 geoProvinces 数组是什么样子的?如果例如是一个对象数组,方式为 [{id:..,nm:...}] 您可以在选项 [value]="item.id" 中使用(直到您不填充 geoProvinces,选择无法显示任何事物)
  • 我更新了问题,我增加了获得省份的方法。在ngOnInit()中,fieldControls['province'].value包含province的值,这是我要默认显示的那个
  • @build,您也可以使用异步管道,但问题是“您的 geoProvinces 数组看起来如何”?
  • 我刚刚更新了问题,我添加了this.geoProvinces 的数组部分
猜你喜欢
  • 2021-07-29
  • 2019-05-28
  • 1970-01-01
  • 2020-11-25
  • 1970-01-01
  • 1970-01-01
  • 2021-07-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多