23

I have a list of interests i am getting from the backend. I want a user to be able to select the interests they want. I will store only the interests they checked in the DB and pre-populate when they load the page. But first i need to get these interests the user has selected.

interest.component.ts

export class InterestsComponent implements OnInit {

  interestFormGroup : FormGroup
  interests:any;
  selected: any;


  constructor(public interestService: InterestService, private formBuilder: FormBuilder,
  ) { }

  ngOnInit() {

    this.interestFormGroup = this.formBuilder.group({
      interests: this.formBuilder.array([])
    });


    this.interestService.all().subscribe((res) => {

      this.interests = res;

    });

  }

  change() {
    console.log(this.interestFormGroup.value);
  }

}

interest.component.html

<div id="interest">

    <div class="interest-list">

        <form [formGroup]="interestFormGroup">
            <div *ngFor="let interest of interests" >
                <mat-checkbox class="example-margin" formNameArray="interests" (change)="change()">{{interest}}</mat-checkbox>
            </div>
        </form>

    </div>

</div>

In my console.log on the change event it shows there is no values being added to the interests array within the interestFormGroup. Even tho the checkboxes are checked.

1 Answer 1

35

You should add controls to FormArray manually like:

this.interests = res;
const formArray = this.interestFormGroup.get('interests') as FormArray;
this.interests.forEach(x => formArray.push(new FormControl(false)));

then change template as follows:

<form [formGroup]="interestFormGroup" (ngSubmit)="submit()">
   <ng-container formArrayName="interests">
      <div *ngFor="let interest of interests; let i = index" >
         <mat-checkbox class="example-margin" [formControlName]="i">
           {{interest}}
         </mat-checkbox>
      </div>
   </ng-container>
   <button>Submit</button>
</form>

And when you will submit form you need to transform FormArray values to your desired result:

submit() {
  const result = Object.assign({}, 
    this.interestFormGroup.value, { 
      interests: this.interests
        .filter((x, i) => !!this.interestFormGroup.value.interests[i])});

  console.log(result);
}

Alternative solution is listen change event and manually add and remove value to FormArray:

<div *ngFor="let interest of interests; let i = index" >
   <mat-checkbox class="example-margin" 
                (change)="onChange($event)" [value]="interest">{{interest}}</mat-checkbox>
</div>

onChange(event) {
  const interests = <FormArray>this.interestFormGroup.get('interests') as FormArray;

  if(event.checked) {
    interests.push(new FormControl(event.source.value))
  } else {
    const i = interests.controls.findIndex(x => x.value === event.source.value);
    interests.removeAt(i);
  }
}

Stackblitz example

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

11 Comments

From the stackblitz thats not what i want, it returns an array of true and false values, when i actually want the value of the interest. As true and false values don't actually tell me what interest was selected as the key is the index. I don't even know why the index is added here? Seems like an over complicated solution to something thats meant to be simple.
So in that stackbltiz example it should return an array of interests with values interest1,interest2,interest3 not 0:true 1:true 2:true
Did you try to submit form? Look at the console
@yurzui how to make select all checkbox in that example? Do you have any idea?
|

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.