Angular 4 - using objects for option values in a s

2020-02-17 09:40发布

问题:

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 an object. Also, I do NOT want to use 2 way data binding. e.g. if my Component has these fields:


    lUsers: any[] = [
        { Name: 'Billy Williams', Gender: 'male' },
        { Name: 'Sally Ride', Gender: 'female'}
        ];
    curUser: any;

I would like my HTML template to contain this:


    <select #selectElem (change)="setNewUser(selectElem.value)">
        <option *ngFor="let user of lUsers" [ngValue]="user">
            {{user.Name}}
        </option>
    </select>

With this code, though, my setNewUser() function receives the contents of the selected user's Name field. Why it picks that specific field, I have no idea. What I expect is that it would receive the "value" of the selected option, which I specifically set to a user object.

Note that I used ngValue instead of value in the option. That was by suggestion of others on SO. If I use value instead, what happens is that the object gets converted to the string '[Object object]', which is what setNewUser() receives, which is useless.

FYI, I'm working on Windows 10, using angular 4.0.0 with @angular/cli 1.1.2. Here is the setNewUser() method:


    setNewUser(user: User): void {

    console.log(user);
    this.curUser = user;
    } // setNewUser()

I am determining just what exactly is being passed to it both my logging it, and also including this on the template: <pre>{{curUser}}</pre>

回答1:

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;
    }


回答2:

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.



回答3:

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/



回答4:

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);
 }


回答5:

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 :)