I know that similar questions have been asked, but I\'ve found none with a good answer. I want to create a select list in an Angular form, where the value for each option is
As value
attribute of option
tag cannot store a whole object we will create a new property id
in the lUsers
array to keep track of the selected item.
HTML :
<select #selectElem (change)="setNewUser(selectElem.value)">
<option *ngFor="let user of lUsers" [value]="user.id">
{{user.Name}}
</option>
</select>
This will pass the unique id
to our setNewUser
function on change.
In your component.ts :
...
lUsers: any[] = [
{ id: 1, Name: 'Billy Williams', Gender: 'male' },
{ id: 2, Name: 'Sally Ride', Gender: 'female'}
];
curUser: any = this.lUsers[0]; // first will be selected by default by browser
...
setNewUser(id: any): void {
console.log(id);
// Match the selected ID with the ID's in array
this.curUser = this.lUsers.filter(value => value.id === parseInt(id));
console.log(this.curUser);
}
Here is the plnkr demo of the above code. Open your developer tools to view the console logs.
You can use [ngValue] instead of [value] on the -Elements. It works for me.
I've found that information here: https://www.reddit.com/r/Angular2/comments/65run4/select_option_using_value_vs_ngvalue/
I'm currently using [ngValue]
and it stores objects just fine.
The explanation as to why you experienced issues using (change)
instead of (ngModelChange)
can be found in this question
So, since you've already used [ngValue]
, you probably want to do something like this, where you will only use one way binding in order to be able to use the ngModelChange directive:
<select (ngModelChange)="setNewUser($event)" (ngModel)="lUsers">
<option *ngFor="let user of lUsers" [ngValue]="user">
{{user.Name}}
</option>
</select>
And your ts file will capture the event and receive the User object without needing to track it by id, basically reusing your old method will be good enough:
setNewUser(user: User): void {
console.log(user);
this.curUser = user;
}
UPDATE 16/06/2020:
Always depending on your use case you may need to use square brackets instead of round here: (ngModel)="lUsers
. For the particular case the OP stated, round brackets was the right choice. A clear and detailed description of the difference between square/round and banana box can be found in this answer from Angular guru Günter Zöchbauer
HTML:
<select [formControl]="years">
<option value="">Select</option>
<option *ngFor="let year of yearsList" [ngValue]="year">{{year.value}}</option>
</select>
TS:
years = new FormControl('');
yearsList = [{id: 1, value: '2019'}, {id:2, value: '2020'}];
this.years.valueChanges.subscribe((year) => {
console.log(year)
});
RESULT: you will get year object in console :)
You can use ngModel and ngValue
<select [(ngModel)]="curUser ">
<option *ngFor="let user of lUsers" [ngValue]="user">
{{user.Name}}
</option>
</select>
ANGULAR 6 SIMPLY DO THIS
HTML
<div class="col-3" style="float:left;padding-left: 18px !important;">
<label>Vehicle No.</label>
<div *ngIf="gpsDevicesArray && gpsDevicesArray.length > 0">
<select [ngModel]="selectedVehicle" style="padding: 7px;border-radius: 4px;"
(ngModelChange)="onVehicleNumberChange($event)">
<option *ngFor=" let device of gpsDevicesArray" [ngValue]="device">
{{device.vehicleNumber}}
</option>
</select>
</div>
</div>
TYPESCRIPT
// For intital Value ( put this line inside server calling function )
this.selectedVehicle = gpsDevicesArray[0];
// listener
onVehicleNumberChange(device) {
console.log("selectedVehicle ====", device);
}