1

I am new to Angular2 (started yesterday) and not an Angular user before this. My question is how can I 2 way bind an array to checkbox in ReactiveFormsModule? Below is my missing piece puzzle code.

<!-- profile.ts -->
export class UserProfileComponent {
    status = {
        ready: false,
        saving: false
    };
    form: FormGroup;
    masterData = {
        skills: [{ id: 'js', text: 'Javascript' }, { id: 'cs', text: 'C#' }]
    };
    constructor(FB: FormBuilder) {
        let self = this;

        self.form = FB.group({
            name: new FormControl('', Validators.required)
            , gender: new FormControl('', Validators.required)
            , skills: new FormArray([])
        })
        self.getProfile()
            .then(profile => {
                return self.loadFormData(profile);
            }).then(() => {
                this.status.ready = true
            });
    }
    getProfile() {
        return new Promise((done, fail) => {
            let sample = { name: 'me', gender: 'm', skills: ['js']};
            done(sample);
        })
    }
    loadFormData({ name, gender, skills = []}) {
        let self = this
            , form = self.form

        return new Promise((done, fail) => {
            form.get('name').setValue(name);
            form.get('gender').setValue(gender);

            skills.reduce((array: FormArray, skill: string) => {
                array.push(new FormControl(skill));
                return array;
            }, form.get('skills'));
            done();
        });
    }
    selectSkill (event, skill) {
        let skills = this.form.get('skills')
            , checked = event.target.checked
            ;

        let index = skills.value.indexOf(skill);
        if (checked === true && index < 0) {
            skills.push(new FormControl(skill));
        } else if (checked === false && index >= 0) {
            skills.removeAt(index);
        }
    }   
};  


<!-- profile.html -->
<div class="title">Profile</div>
<div>
    <form [formGroup]="form" (ngSubmit)="submitForm()">
        <div class="form-group">
            <label for="name">Name</label>
            <input formControlName="name" name="name" class="form-control" placeholder="Name" type="text">
        </div>
        <div class="form-group">
            <label>Gender</label>
        </div>
        <div class="radio-inline">
            <label><input type="radio" name="gender" value="m" formControlName="gender"> Male</label>
        </div>
        <div class="radio-inline">
            <label><input type="radio" name="gender" value="f" formControlName="gender"> Female</label>
        </div>
        <div class="form-group">
            <label>Skill {{ skills }}</label>
        </div>
        <div *ngFor="let skill of masterData.skills">
            <div class="checkbox-inline"><label>
                <input type="checkbox" name="skill" (change)="selectSkill($event, skill.id)"> {{ skill.text }}
            </label></div>
        </div>
        <div>
            <button type="submit" class="btn" [disabled]="form.invalid">Save</button>
        </div>
    </form >
</div>

Everything work fine except I don't know how to make skills checkbox checked after form load based on my sample data?

1 Answer 1

-1

You have to use FormArrayName directive :

// Compoenent

public allSkills = [
  { value : 'cs', label : 'C#' },
  { value : 'js', label : 'Javascript' }
];

constructor(FB: FormBuilder) {
    this.form = FB.group({
        name: new FormControl('', Validators.required),
        gender: new FormControl('', Validators.required),
        skills: new FormArray([])
    });
    for(let skill on this.allSkills) {
      this.form.get('skills').push(new FormControl());
    }
}

// HTML

<form [formGroup]="form" (ngSubmit)="submitForm()">
  <div class="form-group">
    <label for="name">Name</label>
      <input formControlName="name" name="name" class="form-control" placeholder="Name" type="text">
  </div>
  <div class="form-group">
    <label>Gender</label>
  </div>
  <div class="radio-inline">
    <label><input type="radio" name="gender" value="m" formControlName="gender"> Male</label>
  </div>
  <div class="radio-inline">
    <label><input type="radio" name="gender" value="f" formControlName="gender"> Female</label>
  </div>
  <div class="form-group">
    <label>Skills</label>
  </div>
  <div formArrayName="skills">
    <div class="checkbox-inline" *ngFor="let skill of skills.controls; let i=index">
      <label>
        <input type="checkbox" [formControlName]="i" [value]="allSkills[i]['value']"/> {{allSkills[i]['label']}}
      </label>
    </div>
  </div>
  <button type="submit" class="btn" [disabled]="form.invalid"> Save </button>
</form>
Sign up to request clarification or add additional context in comments.

3 Comments

@ranakrunal9 is not an ideal way to keep on push empty FormControl just to map allSkills index
@xe4me from your link I can see use ngModel to bind to boolean variable, it seem different compare to mine since I am using array item. Or did I miss something? If yes, please highlight.

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.