角度材质:mat-select不选择默认值

时间:2017-11-16 15:14:48

标签: angular typescript angular-material2

我有一个mat-select,其中的选项是数组中定义的所有对象。我试图将值设置为默认值为其中一个选项,但是在页面呈现时它会被选中。

我的打字稿文件包含:

DECLARE @date date
DECLARE @datetime datetime

SELECT @datetime = GETDATE()
select @date = GETDATE()

select format(cast(min(@date + @datetime) as datetime), 'hh:mm:ss tt')

我的HTML文件包含:

  public options2 = [
    {"id": 1, "name": "a"},
    {"id": 2, "name": "b"}
  ]
  public selected2 = this.options2[1].id;

我尝试将 <div> <mat-select [(value)]="selected2"> <mat-option *ngFor="let option of options2" value="{{ option.id }}"> {{ option.name }} </mat-option> </mat-select> </div> selected2中的value设置为对象及其ID,并尝试同时使用mat-option[(value)] [(ngModel)],但都没有。

我使用的是素材版本2.0.0-beta.10

由于

19 个答案:

答案 0 :(得分:76)

对模板中的值使用绑定。

value="{{ option.id }}"

应该是

[value]="option.id"

在您选择的值中,使用ngModel代替value

<mat-select [(value)]="selected2">

应该是

<mat-select [(ngModel)]="selected2">

完整代码:

<div>
  <mat-select [(ngModel)]="selected2">
    <mat-option *ngFor="let option of options2" [value]="option.id">{{ option.name }}</mat-option>
  </mat-select>
</div>

version 2.0.0-beta.12的旁注中,material select现在接受mat-form-field元素作为父元素,因此它与其他材质输入控件一致。升级后用div元素替换mat-form-field元素。

<mat-form-field>
  <mat-select [(ngModel)]="selected2">
    <mat-option *ngFor="let option of options2" [value]="option.id">{{ option.name }}</mat-option>
  </mat-select>
</mat-form-field>

答案 1 :(得分:43)

使用compareWith,一个函数将选项值与所选值进行比较。见这里:https://material.angular.io/components/select/api#MatSelect

对于以下结构的对象:

listOfObjs = [{ name: 'john', id: '1'}, { name: 'jimmy', id: '2'},...]

定义这样的标记:

<mat-form-field>
  <mat-select
    [compareWith]="compareObjects"
    [(ngModel)]="obj">
       <mat-option  *ngFor="let obj of listOfObjs" [value]="obj">
          {{ obj.name }}
       </mat-option>
    </mat-select>
</mat-form-field>

定义这样的比较函数:

compareObjects(o1: any, o2: any): boolean {
  return o1.name === o2.name && o1.id === o2.id;
}

答案 2 :(得分:13)

我使用Angular 5和带有mat-select的反应形式,并且无法获得上述任何一种解决方案来显示初始值。

我必须添加[compareWith]来处理mat-select组件中使用的不同类型。在内部,看起来mat-select使用数组来保存所选值。如果打开该模式,这可能允许相同的代码使用多个选择。

Angular Select Control Doc

这是我的解决方案:

表单构建器以初始化表单控件:

this.formGroup = this.fb.group({
    country: new FormControl([ this.myRecord.country.id ] ),
    ...
});

然后在组件上实现compareWith函数:

compareIds(id1: any, id2: any): boolean {
    const a1 = determineId(id1);
    const a2 = determineId(id2);
    return a1 === a2;
}

接下来创建并导出determineId函数(我必须创建一个独立函数,因此mat-select可以使用它):

export function determineId(id: any): string {
    if (id.constructor.name === 'array' && id.length > 0) {
       return '' + id[0];
    }
    return '' + id;
}

最后将compareWith属性添加到mat-select:

<mat-form-field hintLabel="select one">
<mat-select placeholder="Country" formControlName="country" 
    [compareWith]="compareIds">

    <mat-option>None</mat-option>
    <mat-option *ngFor="let country of countries" [value]="country.id">
                        {{ country.name }}
    </mat-option>
</mat-select>
</mat-form-field>

答案 3 :(得分:12)

您应该将其[value]绑定为mat-option,如下所示

<mat-select placeholder="Panel color" [(value)]="selected2">
  <mat-option *ngFor="let option of options2" [value]="option.id">
    {{ option.name }}
  </mat-option>
</mat-select>

<强> LIVE DEMO

答案 4 :(得分:3)

不推荐使用AngModel(已在Angular 6中以反应形式使用ngModel)(并已在Angular 7中删除),因此我按如下所示修改了模板和组件。

模板:

<mat-form-field>
    <mat-select [formControl]="filter" multiple 
                [compareWith]="compareFn">
        <mat-option *ngFor="let v of values" [value]="v">{{v.label}}</mat-option>
    </mat-select>
</mat-form-field>

组件的主要部分(省略了onChanges和其他详细信息):

interface SelectItem {
    label: string;
    value: any;
}

export class FilterComponent implements OnInit {
    filter = new FormControl();

    @Input
    selected: SelectItem[] = [];

    @Input()
    values: SelectItem[] = [];

    constructor() { }

    ngOnInit() {
        this.filter.setValue(this.selected);
    }

    compareFn(v1: SelectItem, v2: SelectItem): boolean {
        return compareFn(v1, v2);
    }
}

function compareFn(v1: SelectItem, v2: SelectItem): boolean {
    return v1 && v2 ? v1.value === v2.value : v1 === v2;
}

请注意上面ngOnInit中的 this.filter.setValue(this.selected)

它似乎可以在Angular 6中使用。

答案 5 :(得分:2)

我的解决方案有点棘手和简单。

<div>
    <mat-select
        [placeholder]="selected2">
      <mat-option
          *ngFor="let option of options2"
          value="{{ option.id }}">
        {{ option.name }}
      </mat-option>
    </mat-select>
  </div>

我只是使用了占位符。材质占位符的默认颜色为light gray。为了使其看起来像已选中该选项,我按如下方式操作了CSS:

::ng-deep .mat-select-placeholder {
    color: black;
}

答案 6 :(得分:2)

对我来说,解决方案是:

<mat-form-field>
  <mat-select #monedaSelect  formControlName="monedaDebito" [attr.disabled]="isLoading" [placeholder]="monedaLabel | async ">
  <mat-option *ngFor="let moneda of monedasList" [value]="moneda.id">{{moneda.detalle}}</mat-option>
</mat-select>

TS:

@ViewChild('monedaSelect') public monedaSelect: MatSelect;
this.genericService.getOpciones().subscribe(res => {

  this.monedasList = res;
  this.monedaSelect._onChange(res[0].id);


});

使用对象:{id:数字,详细信息:字符串}

答案 7 :(得分:1)

我就像在这些示例中一样。试图将mat-select的值设置为mat-options之一的值。但是失败了。

我的错误是将[(value)] =“ someNumberVariable”用于数字类型变量,而mat-options中的变量是字符串。即使它们在模板中看起来相同,也不会选择该选项。

一旦我将someNumberVariable解析为一个字符串,一切就很好了。

因此,看来您需要让mat-select和mat-option值不仅是相同的数字(如果要显示数字),而且还应使它们的类型为string。

答案 8 :(得分:1)

一种非常简单的方法来实现此目的,例如,使用带有默认值的CTCBeamSearchDecoder,例如在formControl(可选)内。这是一个将单位选择器用于区域输入的示例:

ts

FormGroup

html

H_AREA_UNIT = 1;
M_AREA_UNIT = 2;

exampleForm: FormGroup;

this.exampleForm = this.formBuilder.group({
  areaUnit: [this.H_AREA_UNIT],
});

答案 9 :(得分:1)

我非常仔细地遵循了上述内容,但仍然无法选择初始值。

原因是,尽管我的绑定值在打字稿中定义为字符串,但我的后端API返回了一个数字。

JavaScript松散类型只是在运行时更改了类型(没有错误),这阻止了选择初始值。

组件

myBoundValue: string;

模板

<mat-select [(ngModel)]="myBoundValue">

解决方案是更新API以返回字符串值。

答案 10 :(得分:1)

尝试一下!

this.selectedObjectList = [{id:1}, {id:2}, {id:3}]
this.allObjectList = [{id:1}, {id:2}, {id:3}, {id:4}, {id:5}]
let newList = this.allObjectList.filter(e => this.selectedObjectList.find(a => e.id == a.id))
this.selectedObjectList = newList

答案 11 :(得分:0)

数字和字符串之间的比较通常为假,因此,请将您选择的值强制转换为ngOnInit中的字符串,它将起作用。

我遇到了同样的问题,我使用

用一个枚举填充了mat-select
Object.keys(MyAwesomeEnum).filter(k => !isNaN(Number(k)));

并且我具有要选择的枚举值...

我花了几个小时苦苦挣扎,试图找出为什么它不起作用。在渲染了mat-select,keys集合和selected中使用的所有变量之后,我就这样做了。如果您有[“ 0”,“ 1”,“ 2”],并且想要选择1( 1 ==“ 1”为假,因此未选择任何内容。

因此,解决方案是在ngOnInit中将您选择的值投射到字符串中,它将起作用。

答案 12 :(得分:0)

仅当 MatSelect 上的 value 属性与绑定到 MatOption < / strong>。如果将项目的caption绑定到 mat-option 元素的 value 属性,则必须在 mat-select 上设置默认元素到您的项目的caption。如果将项目的Id绑定到 mat-option ,则也必须将id绑定到 mat-select ,而不是整个项目,标题或任何其他字段,只有相同的字段。

但是您需要通过绑定[]

答案 13 :(得分:0)

我做到了

<div>
    <mat-select [(ngModel)]="selected">
        <mat-option *ngFor="let option of options" 
            [value]="option.id === selected.id ? selected : option">
            {{ option.name }}
        </mat-option>
    </mat-select>
</div>

通常,您可以[value]="option"进行操作,除非您从某些数据库中获得选择?我认为要么延迟获取数据导致其无法正常工作,要么即使对象相同,获取的对象还是有所不同?? 奇怪的是,很可能是后来的版本,因为我也尝试过[value]="option === selected ? selected : option",但没有用。

答案 14 :(得分:0)

您可以简单地实现自己的比较功能

[compareWith]="compareItems"

也请参见docu。因此完整的代码如下所示:

  <div>
    <mat-select
        [(value)]="selected2" [compareWith]="compareItems">
      <mat-option
          *ngFor="let option of options2"
          value="{{ option.id }}">
        {{ option.name }}
      </mat-option>
    </mat-select>
  </div>

并在Typescript文件中:

  compareItems(i1, i2) {
    return i1 && i2 && i1.id===i2.id;
  }

答案 15 :(得分:0)

TS

   optionsFG: FormGroup;
   this.optionsFG = this.fb.group({
       optionValue: [null, Validators.required]
   });

   this.optionsFG.get('optionValue').setValue(option[0]); //option is the arrayName

HTML

   <div class="text-right" [formGroup]="optionsFG">
     <mat-form-field>
         <mat-select placeholder="Category" formControlName="optionValue">
           <mat-option *ngFor="let option of options;let i =index" [value]="option">
            {{option.Value}}
          </mat-option>
        </mat-select>
      </mat-form-field>
  </div>

答案 16 :(得分:0)

public options2 = [
  {"id": 1, "name": "a"},
  {"id": 2, "name": "b"}
]
 
YourFormGroup = FormGroup; 
mode: 'create' | 'update' = 'create';

constructor(@Inject(MAT_DIALOG_DATA) private defaults: defautValuesCpnt,
      private fb: FormBuilder,
      private cd: ChangeDetectorRef) {
}
  
ngOnInit() {

  if (this.defaults) {
    this.mode = 'update';
  } else {
    this.defaults = {} as Cpnt;
  }

  this.YourFormGroup.patchValue({
    ...
    fCtrlName: this.options2.find(x => x.name === this.defaults.name).id,
    ... 
  });

  this.YourFormGroup = this.fb.group({
    fCtrlName: [ , Validators.required]
  });

}
  <div>
    <mat-select formControlName="fCtrlName"> <mat-option
          *ngFor="let option of options2"
          value="{{ option.id }}">
        {{ option.name }}
      </mat-option>
    </mat-select>
  </div>

答案 17 :(得分:0)

当页面加载时,我在绑定第一个选项时遇到问题。下面有帮助我的解决方案

.html

<mat-form-field appearance="outline">    
    <mat-select #teamDropdown 
        [ngModel]="selectedGroupId" (selectionChange)="selectedGroupId=$event.value">
        <mat-option value=undefined>Please Select</mat-option>
        <mat-option *ngFor="let grp of groups" [value]="grp.groupsId">
            {{grp.groupName}}
        </mat-option>
    </mat-select>
</mat-form-field>

.ts

@ViewChild('teamDropdown') teamDropdown: MatSelect;
ngAfterViewInit() {
    setTimeout(() => {
        this.selectTeamDropdown.options.first.select();
    });
}

答案 18 :(得分:-2)

在使用角度材质选择时,最好使用 compareWith 函数来比较您的对象。 如果您想了解有关如何使用 mat-select 的更多信息,可以查看以下链接: The importance of the compare function in angular material select