example - Material angular: mat-select no selecciona el valor predeterminado
mat-select-trigger (10)
¡Prueba esto!
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
Tengo un mat-select donde las opciones son todos los objetos definidos en una matriz. Estoy tratando de establecer el valor predeterminado en una de las opciones, sin embargo, se deja seleccionado cuando se presenta la página.
Mi archivo mecanografiado contiene:
public options2 = [
{"id": 1, "name": "a"},
{"id": 2, "name": "b"}
]
public selected2 = this.options2[1].id;
Mi archivo HTML contiene:
<div>
<mat-select
[(value)]="selected2">
<mat-option
*ngFor="let option of options2"
value="{{ option.id }}">
{{ option.name }}
</mat-option>
</mat-select>
</div>
Intenté configurar
selected2
y el
value
en
mat-option
tanto para el objeto como para su id, e intenté usar tanto
[(value)]
como
[(ngModel)]
en
mat-select
, pero ninguno funciona.
Estoy usando la versión de material 2.0.0-beta.10
Como ya se mencionó en Angular 6, el uso de ngModel en formas reactivas está en desuso (y se elimina en Angular 7), por lo que modifiqué la plantilla y el componente de la siguiente manera.
La plantilla:
<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>
Las partes principales del componente (se
onChanges
y otros detalles):
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;
}
Tenga en cuenta
this.filter.setValue (this.selected)
en
ngOnInit
arriba.
Parece funcionar en Angular 6.
Debería vincularlo como
[value]
en la
mat-option
como se muestra a continuación,
<mat-select placeholder="Panel color" [(value)]="selected2">
<mat-option *ngFor="let option of options2" [value]="option.id">
{{ option.name }}
</mat-option>
</mat-select>
Estoy usando Angular 5 y formas reactivas con mat-select y no pude obtener ninguna de las soluciones anteriores para mostrar el valor inicial.
Tuve que agregar [compareWith] para tratar con los diferentes tipos que se utilizan dentro del componente mat-select. Internamente, parece que mat-select usa una matriz para mantener el valor seleccionado. Es probable que esto permita que el mismo código funcione con varias selecciones si ese modo está activado.
Documento de control de selección angular
Aquí está mi solución:
Form Builder para inicializar el control de formulario:
this.formGroup = this.fb.group({
country: new FormControl([ this.myRecord.country.id ] ),
...
});
Luego implemente la función compareWith en su componente:
compareIds(id1: any, id2: any): boolean {
const a1 = determineId(id1);
const a2 = determineId(id2);
return a1 === a2;
}
Luego, cree y exporte la función determineId (tuve que crear una función independiente para que mat-select pudiera usarla):
export function determineId(id: any): string {
if (id.constructor.name === ''array'' && id.length > 0) {
return '''' + id[0];
}
return '''' + id;
}
Finalmente agregue el atributo compareWith a su 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>
La solución para mí fue:
<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);
});
Usando objeto: {id: número, detalle: cadena}
Lo hice como en estos ejemplos. Intenté establecer el valor de mat-select en el valor de una de las opciones de mat. Pero falló.
Mi error fue hacer [(valor)] = "someNumberVariable" en una variable de tipo numérico, mientras que las de las opciones de mat eran cadenas. Incluso si tuvieran el mismo aspecto en la plantilla, no seleccionaría esa opción.
Una vez que analicé el someNumberVariable en una cadena, todo estuvo totalmente bien.
Por lo tanto, parece que necesita tener los valores mat-select y mat-option no solo sean el mismo número (si está presentando números) sino que también deben ser de tipo cadena.
Mi solución es un poco complicada y más simple.
<div>
<mat-select
[placeholder]="selected2">
<mat-option
*ngFor="let option of options2"
value="{{ option.id }}">
{{ option.name }}
</mat-option>
</mat-select>
</div>
Acabo de hacer uso del
marcador
de
posición
.
El color predeterminado del marcador de posición del material es
light gray
.
Para que parezca que la opción está seleccionada, simplemente manipulé el CSS de la siguiente manera:
::ng-deep .mat-select-placeholder {
color: black;
}
Simplemente puede implementar su propia función de comparación
[compareWith]="compareItems"
Ver también el docu . Entonces el código completo se vería así:
<div>
<mat-select
[(value)]="selected2" [compareWith]="compareItems">
<mat-option
*ngFor="let option of options2"
value="{{ option.id }}">
{{ option.name }}
</mat-option>
</mat-select>
</div>
y en el archivo mecanografiado:
compareItems(i1, i2) {
return i1 && i2 && i1.id===i2.id;
}
Use un enlace para el valor en su plantilla.
value="{{ option.id }}"
debiera ser
[value]="option.id"
Y en su valor seleccionado use
ngModel
lugar de
value
.
<mat-select [(value)]="selected2">
debiera ser
<mat-select [(ngModel)]="selected2">
Código completo:
<div>
<mat-select [(ngModel)]="selected2">
<mat-option *ngFor="let option of options2" [value]="option.id">{{ option.name }}</mat-option>
</mat-select>
</div>
En una nota al margen a partir de la
versión 2.0.0-beta.12,
la
selección de material
ahora acepta un elemento
mat-form-field
como elemento padre, por lo que es coherente con los otros controles de entrada de material.
Reemplace el elemento
div
con el elemento
mat-form-field
después de actualizar.
<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>
Utilice
compareWith
, una función para comparar los valores de las opciones con los valores seleccionados.
ver aquí:
https://material.angular.io/components/select/api#MatSelect
Para un objeto de la siguiente estructura:
listOfObjs = [{ name: ''john'', id: ''1''}, { name: ''jimmy'', id: ''2''},...]
Defina marcado como este:
<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>
Y defina una función de comparación como esta:
compareObjects(o1: any, o2: any): boolean {
return o1.name === o2.name && o1.id === o2.id;
}