5

I have a select list that is bound to an Person property on my component using [ngValue]. When I change the select, the underyling selectedPerson property is updated as expected. However, the select does no default to the selected person on initialisation nor does it update if I change the selected person in code.

Any help into what I am missing would be greatly appreciated. Here's my code...

import {Component, OnInit, NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'my-app',
  template: `
      <form>
          <select [(ngModel)]="selectedPerson" 
                  name="selectedPerson">
              <option [ngValue]="null">Please choose...</option>
              <option *ngFor="let p of people"
                      [ngValue]="p"
                      [attr.selected]="p.personId === selectedPerson?.personId ? true : null ">{{p.name}}</option>
          </select>
          <p>The selected person is {{selectedPerson?.name}}</p>
          <button type="button" (click)="selectJane()">Select Jane</button>
          <button type="button" (click)="clearSelection()">Clear Selection</button>
      </form>`,
})
export class App implements OnInit {

  public ngOnInit() {

    this.people = [
      { personId: 1, name: "Tom" },
      { personId: 2, name: "Mary" },
      { personId: 3, name: "Jane" }
    ]
    this.selectedPerson = { personId: 2, name: "Mary" }
  }

  public people: Person[];
  public selectedPerson: Person;  

  public selectJane(){
    this.selectedPerson = { personId: 3, name: "Jane" }
  }

  public clearSelection(){
    this.selectedPerson = null;
  }  
}

export class Person {
  public personId: number;
  public name: string;
}

@NgModule({
  imports: [ BrowserModule, FormsModule ],
  declarations: [ App ],
  bootstrap: [ App ]
})
export class AppModule {}

...and here's a Plunker http://plnkr.co/edit/ag94mZO9Zggg1kZx8jJV

Maximilian Riegler
  • 22,720
  • 4
  • 62
  • 71
Nemir
  • 283
  • 1
  • 3
  • 9
  • Possible duplicate of [angular 2 - bind object to dropdown and select value based on an event](http://stackoverflow.com/questions/39105905/angular-2-bind-object-to-dropdown-and-select-value-based-on-an-event) – Fabio Antunes Sep 28 '16 at 11:10

1 Answers1

7

The problem is, that by using ngValue, the select expects the same reference, not just a similar looking object.

You could add a method to select by name like this:

public selectByName(name: string) {
   this.selectedPerson = this.people.find(person => person.name === name);
}

And then call it in your ngOnInit():

this.selectByName("Mary");
// or this.selectedPerson = this.people[2];

And in selectJane():

public selectJane(){
    this.selectByName("Jane");
}

Your updated Plunker

Maximilian Riegler
  • 22,720
  • 4
  • 62
  • 71
  • 1
    Thanks. That explains the problem clearly and gives me a solution. Having to update the selectedPerson object reference to be the same as the one in the list does feel like a bit of a pain though as in reality, these values would be coming from seperate http calls. I would therefore need to include an extra step to align the references for every select list in my app. I could bind to the id instead which would work but that would mean the is and name would get out of sync; that could be very confusing for a developer trying to debug some other issue. – Nemir Sep 28 '16 at 11:50
  • Thinking about this more, shouldn't the `[attr.selected]="p.personId === selectedPerson?.personId ? true : null"` expression deal with keeping the correct ` – Nemir Sep 28 '16 at 14:36
  • The `selected` attribute doesn't work with `ngModel`. – Maximilian Riegler Sep 28 '16 at 14:56
  • no! no! no!, ng2 team should change this pattern, should not be selecting by object only as html itself cannot work with object. – Long Field Sep 29 '16 at 05:38
  • 1
    I have searched and Googled for hours, having the same problem. References... Why did I not think of that... Thanks! – MadJlzz Feb 21 '17 at 14:02