34

How can I set the default value for all forms fields in angular 2 reactive forms?

Here is the plnkr to reproduce the issue

Below code does not update dropdown values as it has an object associated with it.

Note: Here I need to set the default value for all form fields with the response received from Backend API.

Component.html

<form [formGroup]="myForm" novalidate (ngSubmit)="save(myForm.value, myForm.valid)">
    <div class="form-group">
        <label>Country:</label>
        <select formControlName="country">
          <option *ngFor="let country of masterCountries" [ngValue]="country">{{country.countryName}}</option>
        </select>
    </div>

    <div class="form-group">
      <label for="">Name</label>
      <input type="text" class="form-control" formControlName="name">
      <small [hidden]="myForm.controls.name.valid || (myForm.controls.name.pristine && !submitted)" class="text-danger">
            Name is required (minimum 5 characters).
          </small>
      <!--<pre class="margin-20">{{ myForm.controls.name.errors | json }}</pre>-->
    </div>
    <button type="submit" class="btn btn-default">Submit</button>
    <div class="margin-20">
      <div>myForm details:-</div>
      <pre>Is myForm valid?: <br>{{myForm.valid | json}}</pre>
      <pre>Is myForm submitted?: <br>{{submitted | json}}</pre>
      <pre>myForm value: <br>{{myForm.value | json}}</pre>
    </div>

Component.ts

export class AppComponent implements OnInit {
    public myForm: FormGroup;
    public masterCountries: any[] = [{"countryCode":"AF","countryName":"Afghanistan"},{"countryCode":"AL","countryName":"Albania"},{"countryCode":"DZ","countryName":"Algeria"},{"countryCode":"AS","countryName":"American Samoa"},{"countryCode":"AD","countryName":"Andorra"}];

    // Sample response received from backend api
    public CountryResponse = {country: {"countryCode":"AF","countryName":"Afghanistan"}, name: 'test123'};
    constructor(private _fb: FormBuilder) { }

    ngOnInit() {

        // the short way
        this.myForm = this._fb.group({
            country: [''],
            name: ['', [<any>Validators.required, <any>Validators.minLength(5)]],
        });


        (<FormGroup>this.myForm)
            .setValue(this.CountryResponse, {onlySelf: true});


    }


    save(model: User, isValid: boolean) {
        this.submitted = true;
        console.log(model, isValid);
    }
}

Let me know if there is any other way to set the whole form.

Amr Eladawy
  • 4,193
  • 7
  • 34
  • 52
Narendra CM
  • 1,416
  • 3
  • 13
  • 23
  • 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 29 '16 at 10:11
  • And also a duplicate of http://stackoverflow.com/questions/39745629/angular2-two-way-binding-to-select-option-not-updating – Fabio Antunes Sep 29 '16 at 10:13
  • 2
    It is not a duplicate. I need to update all form fields with the sample response received from backend. updated my question to reflect the same – Narendra CM Sep 29 '16 at 10:24

4 Answers4

50

I know this is an old question, but if anyone looks for it, there is now a better way to set value in the whole form, with PatchValue:

this.myForm.patchValue({
   country: this.CountryResponse,
   name: 'Any Name'
});

this also allows partial, so you would still be able to do something like:

this.myForm.patchValue({ country: this.CountryResponse });

or you can set the value into a single control:

this.myForm.get('country').setValue(this.CountryResponse);
daremachine
  • 2,678
  • 2
  • 23
  • 34
DeBorges
  • 712
  • 1
  • 7
  • 9
16

When you declare the form control or initialise pass the default value as a parameter

  MyFormControl: FormControl = new FormControl('Default value');
Omkar Dixit
  • 746
  • 1
  • 9
  • 19
13

Just change this:

 (<FormGroup>this.myForm)
            .setValue(this.CountryResponse, {onlySelf: true});

Into this:

const selectedCountry = this.masterCountries.find(country => country.countryCode === this.CountryResponse.country.countryCode)
this.CountryResponse.country = selectedCountry;
(<FormGroup>this.myForm)
            .setValue(this.CountryResponse, {onlySelf: true});

As said before you need to pass the exact same reference of the object

Anaa
  • 1,191
  • 1
  • 9
  • 21
Fabio Antunes
  • 22,251
  • 15
  • 81
  • 96
10

Your code does not work because although your this.selectedCountry appears to have the same fields' values with one of the elements of this.masterCountries, they are not the same object. That makes select.value === option.value comparison always returns false.

It's simple to make it works, just change your setValue function to as follow:

(<FormControl>this.form.controls['country'])
            .setValue(this.masterCountries[0], { onlySelf: true });

Or you can just set it when creating the FormGroup:

    this.myForm = this._fb.group({
        country: [this.masterCountries[0]],
        name: ['', [<any>Validators.required, <any>Validators.minLength(5)]],
    });
Harry Ninh
  • 16,288
  • 5
  • 60
  • 54
  • 1
    Thanks for the answer. Yes it works if i use the masterCountries to set the value. But I need to set the whole form with the response received from backend. Updated my plnkr with thsi scenario. https://plnkr.co/edit/GKguMzZbr0kzrraPP73f?p=preview – Narendra CM Sep 29 '16 at 10:14