角材料:垫选择不选择默认
Posted
技术标签:
【中文标题】角材料:垫选择不选择默认【英文标题】:Angular Material: mat-select not selecting default 【发布时间】:2018-04-30 04:46:20 【问题描述】:我有一个 mat-select,其中选项是数组中定义的所有对象。我正在尝试将值设置为默认选项之一,但是在页面呈现时它处于选中状态。
我的打字稿文件包含:
public options2 = [
"id": 1, "name": "a",
"id": 2, "name": "b"
]
public selected2 = this.options2[1].id;
我的 html 文件包含:
<div>
<mat-select
[(value)]="selected2">
<mat-option
*ngFor="let option of options2"
value=" option.id ">
option.name
</mat-option>
</mat-select>
</div>
我尝试将selected2
和mat-option
中的value
设置为对象和它的ID,并尝试在mat-select
中同时使用[(value)]
和[(ngModel)]
,但都没有工作。
我正在使用材料版本 2.0.0-beta.10
【问题讨论】:
使用compareWith
。它更优雅。
必须有compareWith
,在此处查看badis 答案***.com/questions/47333171/…
【参考方案1】:
对模板中的值使用绑定。
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>
【讨论】:
"看起来您在与 formControlName 相同的表单字段上使用 ngModel。Angular v6 中已弃用支持使用 ngModel 输入属性和 ngModelChange 事件与反应式表单指令,并将在Angular v7。有关这方面的更多信息,请在此处查看我们的 API 文档:angular.io/api/forms/FormControlName#use-with-ngmodel" @ldgorman - 我不明白你是如何得出这个结论的。如果您指的是mat-form-field
,这是..."used to wrap several Angular Material components and apply common Text field styles"
,所以不是一回事。除此之外,OP 和我的回答都没有提到 FormControl
、FormGroup
或 FormControlName
。
即使在实现了与上述@Igor 相同的代码后,我也遇到了同样的问题
@Igor- 我们想通了,该值作为一个数字返回,而 Mat-select 它正在寻找一个字符串。 [compareWith]
指令是我们使用的
支持使用 ngModel 输入属性和带有响应式表单指令的 ngModelChange 事件已在 Angular v6 中弃用,并将在 Angular v7 中删除。这个答案不再起作用了。请将其定义为最大支持到 v6 或删除【参考方案2】:
您应该在mat-option
中将其绑定为[value]
,如下所示,
<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
【讨论】:
这非常有效。使用 ngModel 或 setValue() 这是最简单和完美的方法【参考方案3】:我正在使用 Angular 5 和带有 mat-select 的反应形式,并且无法获得上述任何一种解决方案来显示初始值。
我必须添加 [compareWith] 来处理 mat-select 组件中使用的不同类型。在内部,mat-select 似乎使用一个数组来保存选定的值。如果打开该模式,这可能允许相同的代码处理多个选择。
Angular Select Control Doc
这是我的解决方案:
Form Builder 初始化表单控件:
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>
【讨论】:
非常感谢!很难找到原因。 @Heather92065 这是唯一对我有用的解决方案。非常感谢你! @Heather92065 如果要比较的键值是 Input() 值,这将如何工作?我的场景是我有一个可重用的组件,它需要知道提取值是什么才能显示它。比较函数在此值有效之前运行。你如何解决这个问题?【参考方案4】:使用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;
【讨论】:
在处理对象而不是简单数组时非常完美。谢谢。【参考方案5】:试试这个!
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
【讨论】:
【参考方案6】:我的解决方案有点棘手和简单。
<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;
【讨论】:
【参考方案7】:正如 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 中工作。
【讨论】:
这实际上应该是最好的答案,因为这也涵盖了在处理要比较的两个不同 API 结果时的对象选择。 (例如,要从中选择的项目的总列表以及在另一个 api 调用中选择的项目)。 Angular 7 仍然适用于模板驱动模型!但是你不能将它与同一个模板上的反应形式混合。您对[compareWith]
的提示很棒【参考方案8】:
我的解决方案是:
<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: number, detalle: string
【讨论】:
【参考方案9】:您可以简单地实现自己的比较功能
[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;
【讨论】:
这对我有用,我认为这主要是正确的方法,但如果列表只包含一个元素,它就不起作用。谢谢 只有一个元素会出现什么样的异常?因为如果i1
或 i2
不存在,比较应该负责。【参考方案10】:
我就像在这些例子中那样做。试图将 mat-select 的值设置为 mat-options 之一的值。但失败了。
我的错误是对数字类型变量执行 [(value)]="someNumberVariable" 而 mat-options 中的变量是字符串。即使它们在模板中看起来相同,它也不会选择该选项。
一旦我将 someNumberVariable 解析为字符串,一切都很好。
所以看起来你需要让 mat-select 和 mat-option 值不仅是相同的数字(如果你正在呈现数字),而且还要让它们是字符串类型。
【讨论】:
这也是我的问题。一个是数字,另一个是字符串。【参考方案11】:数字和字符串之间的比较通常为假,因此,将您选择的值转换为 ngOnInit 中的字符串即可。
我有同样的问题,我用枚举填充了 mat-select,使用
Object.keys(MyAwesomeEnum).filter(k => !isNaN(Number(k)));
我有我想要选择的枚举值...
我花了几个小时在脑海中挣扎,试图找出它不起作用的原因。我只是在渲染了 mat-select 中使用的所有变量、键集合和选定的...如果你有 ["0","1","2"] 并且你想选择 1 (这是一个数字)1=="1" 为假,因此没有选择任何内容。
所以,解决方案是将您选择的值转换为 ngOnInit 中的字符串,它会起作用。
【讨论】:
嗨,Juan,你可能想看看这篇文章,其中详细介绍了 JS 中不同的相等运算符:***.com/questions/359494/… 嗨威廉,这是一个很棒的帖子,我去过那里几次......我学会了如何正确比较(我希望,我总是可以查看文档)......问题这里是绑定,由材质控制器强制使用不同的类型、数字和字符串...该控制器期望具有相同的类型,因此,如果选择的是数字,则集合必须是数字的集合...这就是问题所在。【参考方案12】:仅当 MatSelect 上的 value 属性与绑定到 MatOptionvalue 属性相当时,默认值的绑定或设置才有效/强>。如果您将项目的caption
绑定到 mat-option 元素的 value 属性,则必须将 mat-select 上的默认元素设置为 @ 987654322@ 您的商品也是如此。如果您将项目的Id
绑定到mat-option,您也必须将id
绑定到mat-select,而不是整个项目、标题或任何其他,只有同一个字段。
但你需要通过绑定[]来做到这一点
【讨论】:
【参考方案13】:我这样做了。
<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】:我非常仔细地按照上面的操作,仍然无法选择初始值。
原因是虽然我的绑定值在打字稿中定义为字符串,但我的后端 API 却返回了一个数字。
javascript 松散类型只是在运行时更改类型(没有错误),这会阻止选择初始值。
组件
myBoundValue: string;
模板
<mat-select [(ngModel)]="myBoundValue">
解决方案是更新 API 以返回字符串值。
【讨论】:
【参考方案15】:实现此目的的一个非常简单的方法是使用带有默认值的formControl
,例如在FormGroup
(可选)中。这是一个将单位选择器用于区域输入的示例:
ts
H_AREA_UNIT = 1;
M_AREA_UNIT = 2;
exampleForm: FormGroup;
this.exampleForm = this.formBuilder.group(
areaUnit: [this.H_AREA_UNIT],
);
html
<form [formGroup]="exampleForm">
<mat-form-field>
<mat-label>Unit</mat-label>
<mat-select formControlName="areaUnit">
<mat-option [value]="H_AREA_UNIT">h</mat-option>
<mat-option [value]="M_AREA_UNIT">m</mat-option>
</mat-select>
</mat-form-field>
</form>
【讨论】:
【参考方案16】: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>
【讨论】:
【参考方案17】: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>
【讨论】:
这将有助于您在安全组件中使用编辑和更新,【参考方案18】:在使用角度材质选择时,最好使用 compareWith 函数来比较您的对象。 如果您想了解有关如何使用 mat-select 的更多信息,可以查看以下链接: The importance of the compare function in angular material select
【讨论】:
【参考方案19】:页面加载时,我在绑定第一个选项时遇到问题。下面有帮助我的解决方案
.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.teamDropdown.options.first.select();
);
【讨论】:
你的意思是:this.teamDropdown .options.first.select();【参考方案20】:唯一的解决方案是你的表单控件或 Ng Model 值在 mat select 标记中必须与分配给选项标记中的值的文本匹配 这是 ts文件
selectedFood = 'Tacos';
模板
<mat-form-field appearance="fill">
<mat-label>Favorite Food</mat-label>
<mat-select [(value)]="selectedFood">
<mat-option value=''>---------</mat-option>
<mat-option value='Tacos'>Tacos</mat-option>
<mat-option value='Pizza'>Pizza</mat-option>
</mat-select>
</mat-form-field>
<p>You selected: selectedFood</p>
【讨论】:
以上是关于角材料:垫选择不选择默认的主要内容,如果未能解决你的问题,请参考以下文章