Angular 7 and angular material how to get the selected option text of mat-select instead of its value
Solution 1
Updated the code, and added click
event on the options
https://stackblitz.com/edit/angular-material-w89kwc?embed=1&file=app/app.component.ts
Added one function
getInnerText(innerText){
console.log(innerText)
}
Added click event in view
<mat-option *ngFor="let familyRelation of familyRelationArray;" [value]="familyRelation.family_relation_id" (click)="getInnerText(familyRelation.family_relation_type)">
{{familyRelation.family_relation_type}}
</mat-option>
Solution 2
Sorry for being late to the party. I'm really horrified of reading all answers above...
The solution is much easier and direct than any of the proposed answers, as the select component just passes the selected model as part of the selectionChange
argument.
But first, some corrections to your example. You've declared an interface, so USE IT:
export interface FamilyRelation {
id: number;
type: string;
}
So, in your constructor:
constructor() {
this.familyRelationArray=[
{
id: 1,
type: 'Parent'
},
{
id: 2,
type: 'Sister'
}
]
}
and not what you put in your StackBlitz... Then your view will become this:
<mat-select (selectionChange)="onChange($event)" id="family_relation" placeholder="Family Relation">
<mat-option *ngFor="let familyRelation of familyRelationArray;" [value]="familyRelation.id">
{{familyRelation.type}}
</mat-option>
</mat-select>
No need for the (click) handler for every mat-option, since it isn't necessary and could lead to performance issues if you have a lot of options. Now, on the controller:
onChange(ev: any) {
let optionText = ev.source.selected.viewValue;
console.log(optionText);
}
or, if you prefer, the typed variant:
onChange(ev: MatSelectChange) {
let optionText = (ev.source.selected as MatOption).viewValue; //use .value if you want to get the key of Option
console.log(optionText);
}
but don't forget the imports...
import { MatSelectChange } from '@angular/material/select';
import { MatOption } from '@angular/material/core';
Solution 3
You can add index to loop with mat-option then pass it to onChange() method and it will allow you to get the selected element from array.
<mat-select #familyRelation (selectionChange)="onChange($event.value, element, i, 'hh')" id="family_relation" placeholder="Family Relation">
<mat-option *ngFor="let familyRelation of familyRelationArray; let i=index" [value]="i">
{{familyRelation.family_relation_type}}
</mat-option>
</mat-select>
onChange(index, data, i, type) {
console.log(this.familyRelationArray[index].family_relation_type);
}
Here you have update code: link
Solution 4
Use the compareWith
<mat-select #familyRelation [compareWith]="compareFn" id="family_relation" formControlName="fr" placeholder="Family Relation">
<mat-option *ngFor="let familyRelation of familyRelationArray;" [value]="familyRelation.family_relation_id">
{{familyRelation.family_relation_type}}
</mat-option>
</mat-select>
compareFn(data1 , data2){
}
compareWith
listen to the 'change' event because 'input' events aren't fired for selects in Firefox. DOC.
Solution 5
Although it is a bit late, but answers have inspired me a bit, here is an idea:
export interface IFamilyGroup{
id: number;
name: string;
address: string;
}
familyGroup: IFamilyGroup[];
getSelectOption( family: IFamilyGroup ): void {
console.log(family);
}
<mat-select (selectionChange)="getSelectOption( familyGroup[$event.value] )">
<mat-option>none</mat-option>
<mat-option
*ngFor="let family of familyGroup; let i = index"
value="{{i}}">
{{ family.name }}
</mat-option>
</mat-select>
The disadvantage of this method is that you cannot use formControlName, because mat-option uses index as value, so if you want to match formgroup, you can change it to this:
// this is formgroup data model
export interface IFamilyGroup{
id: number;
name: string;
address: string;
}
export interface IFormGroupDataForm{
family: FormControl;
whatever1?: FormControl;
whatever2?: FormControl;
}
dataForm: FormGroup;
family = new FormControl();
familyGroup: IFamilyGroup[];
constructor(
private formBuilder: FormBuilder
) { }
ngOnInit(): void {
this.initFormGroup();
}
private initFormGroup() {
dataForm = this.fromFormGroupModel({
family: this.family
// any you need...
});
}
private fromFormGroupModel( model: IFormGroupDataForm ): FormGroup {
return this.formBuilder.group(model);
}
getSelectOption( family: IFamilyGroup ): void {
this.family.setValue(family); // set family data object be value
}
<div [formGroup]="dataForm">
<mat-select (selectionChange)="getSelectOption( familyGroup[$event.value] )">
<mat-option>none</mat-option>
<mat-option
*ngFor="let family of familyGroup; let i = index"
value="{{i}}">
{{ family.name }}
</mat-option>
</mat-select>
//...
</div>
Related videos on Youtube
alim1990
Updated on November 01, 2021Comments
-
alim1990 over 2 years
I need to get the selected text of material drop down list
<mat-select>
instead of its value:<ng-container matColumnDef="fr"> <th mat-header-cell *matHeaderCellDef> Family Rel. </th> <td mat-cell *matCellDef="let element; let i = index;"> <div [formGroupName]="i"> <mat-form-field color="warn" appearance="outline"> <mat-label>Family Relation</mat-label> <mat-select #familyRelation (selectionChange)="onChange(element, i, 'hh')" id="family_relation" formControlName="fr" placeholder="Family Relation"> <mat-option *ngFor="let familyRelation of familyRelationArray;" [value]="familyRelation.family_relation_id"> {{familyRelation.family_relation_type}} </mat-option> </mat-select> </mat-form-field> </div> </td> </ng-container>
And here is how I am trying to do:
@ViewChild('familyRelation') familyRel: ElementRef;
And on change selection of the drop list:
onChange(data, i, type) { let c = this.familyRel.nativeElement.innerText; console.log(c) }
I had the following error:
ERROR TypeError: Cannot read property 'innerText' of undefined at
And when I remove
innerText
, the consoled value is:undefined
What I need as you can see in the stackblitz, if I chosed
Parent
, I want to getParent
into a variable and not1
which is itsid
.Please note that
element
,i
andhh
in(selectionChange)=onChange(element,...)
are used later in the function, so forget about it now. -
alim1990 over 5 yearsAre you sure ? It gave me
innerText does not exists
error even on stackblitz -
alim1990 over 5 yearsIt worked. Is it a long time solution or just temporary ?
-
Rohit.007 over 5 yearsHave you checked on this link
https://stackblitz.com/edit/angular-material-w89kwc?embed=1&file=app/app.component.ts
-
alim1990 over 5 yearsLook what is happening. This drop list is a form control array. When I change the selected option, it gave me the old selected option.
-
Rohit.007 over 5 yearsIf I'm checking on the link, and changing the values, I'm getting the exact value in the console which is selected by me
-
Rohit.007 over 5 yearsYou must be checking jkubm answer. the both issue exists in that link
-
alim1990 over 5 yearsWait. I updated the stackblitz, check it: stackblitz.com/edit/angular-material-wuavbe
-
alim1990 over 5 yearsIt worked but check the link, it is reading the previous value when
getData()
is fired: stackblitz.com/edit/angular-material-wuavbe -
Rohit.007 over 5 yearsOkay, as you are checking in the onChange method of mat. Actually, the onChange runs before the onClick of option thats why you are getting the previous value. Do you still need onchage of mat-select?
-
alim1990 over 5 yearsYes. As I want to run
getData()
. If both can be run throughonClick
it is okay with that, but how to do it ? -
Rohit.007 over 5 yearsyou can do any stuff in getInnerText() method, which you were doing in onChange. stackblitz.com/edit/…
-
alim1990 over 5 yearsIt will work on all drop down lists ? because I have a form array of this drop list for each user? let me try it.
-
MegaCasper about 5 yearsAs far as I can see in your example, the
mat-option
index is not accessible onmat-select
level. -
Rin and Len over 4 yearsThis should be the accepted anwer. Includes typings, also the simplest answer I have seen of a lot of answers. One minor improvement, you can simplify the import statements into just 1:
import {MatSelectChange, MatOption} from '@angular/material';