32
votes

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.

4
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

4 Answers

13
votes

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

47
votes

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);
12
votes

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

  MyFormControl: FormControl = new FormControl('Default value');
10
votes

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