1

I have a question regarding Angular 2 reactive forms. I'm trying to do two things in my reactive form view:

  1. Have a default value in the dropdown of country name.

  2. Change the country code input field based on the selection of the country name field. See html below is.

country.ts

export class Country {
  countryName: string;
  countryCode: number
}

in-memory-data.service.ts which is my database

import { InMemoryDbService } from 'angular-in-memory-web-api';
import { Injectable }    from '@angular/core';

@Injectable()
export class InMemoryDataService implements InMemoryDbService {`

   createDb() {
    let countries = [
      {
          countryName: 'Saudi Arabia',
          countryCode: '+966'
      }, {
          countryName: 'Bahrain',
          countryCode: '+973'
      }, {
          countryName: 'United Kingdom',
          countryCode: '+44'
      },{
          countryName: 'United Arab Emirates',
          countryCode: '+967'
      },{
          countryName: 'Brazil',
          countryCode: '+55'
      },{
          countryName: 'Czech Republic',
          countryCode: '+420'
      }
    ];
    return {countries};
  }
}

html

<div class="container">

<div class="row">
    <h1 id="header-1"> {{title}}</h1>
    <div id="instructions">
        <p>line 1 for description</p>
        <p>line 2 for description</p>

    </div>
</div>

<form class=" form form-inline" [formGroup]="userForm" novalidate>
    <div class="row from-inline" formArrayName="users">
        <div *ngFor="let user of userForm.controls.users.controls; let i=index">
            <div class="heading">
                <span>{{i + 1}}.{{name}} </span>
                <span class="glyphicon glyphicon-remove pull-right" *ngIf="userForm.controls.users.controls.length > 1"
                   (click)="removeDependent(i)"></span>
            </div>
            <div class="body" [formGroupName]="i">
                <div class="row row-form-fields">
                    <div class="form-group col-xs-12 col-sm-6 col-lg-4">
                        <label class="sr-only" for="countryName">Country name</label>
                        <select class="form-control" id="countryName" formControlName="countryName" >
                            <option *ngFor="let country of countries" [ngValue]="country" >{{country.countryName}}</option>
                        </select>
                        <input type="text" class="form-control" formControlName="countryCode" id="countryCode"/>
                        <div [hidden]="userForm.controls.users.controls[i].controls.countryName.valid ||
                                  (userForm.controls.users.controls[i].controls.countryName.pristine && !submitted)" class="error-alert">
                       country is required
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <legend/>
    <div class="form-group">
        <div class="row user-form-btns">
            <div class="col-1-3">
                <template ngbModalContainer/>
                <dependent-modal-component/>
            </div>
            <div class="col-1-3">
                <button class="btn btn-form" (click)="addDependentForm()">add dependents</button>
            </div>
            <div class="col-1-3">
                <button type="submit" class="btn btn-form" id="btn-submit-form" (click)="onSubmit(userForm.value, userForm.valid)"
                    [disabled]="!userForm.valid">Submit</button>
            </div>

        </div>
    </div>
</form>
<div class="row">
    <pre>Is myForm valid?: <br>{{userForm.valid | json}}</pre>
        <pre>form value: <br>{{userForm.value | json}}</pre>
</div>

1 Answer 1

2

If you want to set a default value for a control you can do it when you build the form:

FormBuilder

constructor(dataService: InMemoryDataService, private fb: FormBuilder) {
    this.name = 'Angular2';
    this.countries = dataService.createDb().countries;
    this.userForm = new FormGroup({
                       users: new FormArray([])
                    });

    let fg1 = new FormGroup({
      countryName: new FormControl(this.countries[0].countryName),
      countryCode: new FormControl(this.countries[0].countryCode)
    });

Then we will subscribe to the changes on the countryName control to update the countryCode:

    fg1.controls.countryName.valueChanges.subscribe((countryName) => {
        fg1.controls.countryCode.setValue(this.findCountryCodeByCountryName(countryName));
    });
}

Adding a new user:

addDependent() {
    let newGroup = new FormGroup({
          countryName: new FormControl(this.countries[0].countryName),
          countryCode: new FormControl(this.countries[0].countryCode)
        });

    newGroup.controls.countryName.valueChanges.subscribe((countryName) => {
      newGroup.controls.countryCode.setValue(this.findCountryCodeByCountryName(countryName));
    });

    this.userForm.controls.users.push(newGroup);
  }

The HTML bindings will follow on a per group basis:

<div class="body" [formGroupName]="i">
             <div class="row row-form-fields">
               <div class="form-group col-xs-12 col-sm-6 col-lg-4">
                 <label class="sr-only" for="countryName">Country name</label>
                 <select class="form-control" id="countryName" formControlName="countryName">
                   <option *ngFor="let country of countries" [ngValue]="country.countryName">{{country.countryName}}</option>
                 </select>
                 <input type="text" class="form-control" formControlName="countryCode" id="countryCode"/>
                 <div [hidden]="userForm.controls.users.controls[i].valid ||
                                (userForm.controls.users.controls[i].pristine && !submitted)" class="error-alert">
                     country is required
                     </div>
                 </div>
               </div>
            </div>

Using the countryName binding instead of binding the entry country selected adds some overhead where we have to do a lookup every time the value changes instead of just piggybacking off of what we already have stored, but that's what you wanted.

Here's a plunker: http://plnkr.co/edit/T7QcTcPKB1g7h0GbKYSu?p=preview

Sign up to request clarification or add additional context in comments.

4 Comments

hello, i want to add one more thing. i am creating a form array and the form group is inside it. I did not get why did you use (myForm.controls.countryName.valid) instead of the full thing (userForm.controls.users.controls[i].controls.countryName.valid). I edited my question to add the entire html above
Updated answer and plunker to address your concerns. You didn't have the FormArray excplicitly mentioned in your original question whatsoever so that wasn't addressed.
very sorry about that my mistake .. really appreciate you great help
Thanks for the example -- it was exactly what I needed to see where I'd gone wrong with my own update-a-field problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.