How to Set Initial Value of Angular 2 Reactive Select

Kildareflare picture Kildareflare · Feb 1, 2017 · Viewed 10.4k times · Source

I have a select list which I want to intialise to a saved value returned from the server. But whatever I try I cannot get it to use the selected value.

I am using Angular 2.2.0 and Reactive Forms.

Here is list of values for the select list.

private categoryList: ICategory[] = [
    new Category({ id: 1, name: 'Cat 1' }),
    new Category({ id: 2, name: 'Cat 2' }),
    new Category({ id: 3, name: 'cat 3' })
];

The saved value is:

{ id: 1, name: 'Cat 1' }

Using FormBuilder I create the form

   this.itemForm = this.fb.group({
      name: [null, Validators.required],
      description: [null, Validators.required],
      weight: [null, Validators.required],
      dimensions: [null, Validators.required],
      category:  [null, Validators.required] 
    });

I then initialise it with the saved data

  (<FormGroup>this.itemForm)
        .setValue({
          name: item.name,
          description: item.description,
          weight: item.weight,
          dimensions: item.dimensions,
          category: item.category 
        }, { onlySelf: true });

The template looks like this

<select name="category" [formControl]="itemForm.controls['category']">
         <option [selected]="itemForm.controls['category'].value == null" value="">-- Select --</option>
        <option *ngFor="let cat of categories" [ngValue]="cat">  
            {{cat.name}}
        </option>
    </select>
{{itemForm.controls['category'].value | json }}

Expected Result The name of item one is selected in the select and matches the text in the JSON displayed under template

Actual Behaviour The JSON shows this:

 { "id": 1, "name": "Cat 1" }

But nothing is selected in the select

If --Select-- is chosen the JSON updates correctly to "".

If another cat is chosen, the JSON also updates correctly.

What am I doing wrong, how do initialise the select?

EDIT I also tried this:

<option *ngFor="let cat of categories" [selected]="itemForm.controls['category'].value.id == cat.id" [ngValue]="cat">

Answer

AJT82 picture AJT82 · Feb 1, 2017

If I understand you correctly, you want to set an default value. Then you could just refer to your item.category + the index of the value you want to set.

I would set the values like this, where we set the first item as a default value.

setValues() {
    this.itemForm
        .setValue({
            name: item.name,
            category: item.category[0].id
        })
}

and then use formGroup and formControlName in the form, so:

<form [formGroup]="itemForm">
  <input formControlName="name"/>
  <small *ngIf="!itemForm.controls.name.valid">Name is required!</small>
  <!-- More code -->
  <select formControlName="category">
    <! -- set ngValue to cat.id --> instead of just cat!
    <option *ngFor="let cat of categories" [ngValue]="cat.id">  
      {{cat.name}}
    </option>
  </select>
</form>

Set the [ngValue] (or use just [value]) to either cat.name or cat.id depending on what you want to use, so if you are using ngValue, that doesn't bind the whole object!

Here is a working Plunker. Not knowing where you set the values, at which point, I have made a setValues-button in the plunker that mimics if the values are set later.

Hope this help!