Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 two-way binding to select option not updating

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

like image 480
Nemir Avatar asked Sep 28 '16 11:09

Nemir


People also ask

How to bind two-way data in angular?

You can see that the former is property binding where as the latter is event binding and the combination of both results in two-way binding in Angular. Syntax for two-way data binding in Angular is [ ()]. The [ ()] syntax combines the brackets of property binding, [], with the parentheses of event binding, ().

What is the [ () ] syntax in Angular 2?

The [ ()] syntax combines the brackets of property binding, [], with the parentheses of event binding, (). This syntax for two-way binding is also known as banana in a box. [ ( )] = BANANA IN A BOX It is just a visual way to remember that the parentheses go inside the brackets. In Angular ngModel directive is used for two-way bindings.

What is the role of ngmodel directive in Angular 2?

So here the role of NgModel directive comes into the picture to work as bridge that enables two-way binding to HTML elements. It provides the required name pattern of target as ngModel in property binding and ngModelChange in event binding.

How to change the color of text using ngmodel for two-way binding?

A default color initialized by component property will be selected initially in select box and a sample text is using that color. On change of color in select box, the color of text will change. Here we are using NgModel for two-way binding.


1 Answers

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

like image 176
rinukkusu Avatar answered Sep 27 '22 17:09

rinukkusu