1

I have a edit profile form. for has dynamic checkbox. if user updated the check box once then it should checked default.

Here is my ts file...

import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { ApplicantsService } from '@app/services/applicants.service';

@Component({
  selector: 'app-profile',
  templateUrl: './profile.component.html',
  styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {

  myForm: FormGroup;
  submitted = false;
 
  userid: any;
  
  skills: any;
  experience: any;
  applicant_skills: any;
  profile: any;
  states: any;
  cities: any;
  profilePicture: any;

  constructor(
    private formBuilder: FormBuilder,
    private applicantsService: ApplicantsService,
  ) { }

  ngOnInit(): void {
    
    this.userid = JSON.parse(localStorage.getItem('currentUser')).user_id;

    this.myForm = this.formBuilder.group({
      userid: [''],
      first_name: new FormControl({value: null, disabled: true}, Validators.required),
      last_name: new FormControl({value: null, disabled: true}, Validators.required),
      email: new FormControl({value: null, disabled: true}, Validators.required),
      mobile: ['', Validators.required],
      state: ['', Validators.required],
      city: ['', Validators.required],
      skills: this.formBuilder.array([], [Validators.required]),
    });
    
    this.applicantsService.getProfile(this.userid).subscribe( res => {
      this.profile = res.data[0];
      this.myForm.patchValue(this.profile); 
    })

    this.applicantsService.getApplicantskills(this.userid).subscribe( res => 
    {
      if(res && res.data)
      {
        this.applicant_skills = res.data;
        
        
      }
    })


  }


  // convenience getter for easy access to form fields
  get f() { return this.myForm.controls; }

 


  onCheckboxChange(e) {
    const checkArray: FormArray = this.myForm.get('skills') as FormArray;

    if (e.target.checked) {
      checkArray.push(new FormControl(e.target.value));
    } else {
      let i: number = 0;
      checkArray.controls.forEach((item: FormControl) => {
        if (item.value == e.target.value) {
          checkArray.removeAt(i);
          return;
        }
        i++;
      });
    }
  }

  onSubmit()
  {
      this.submitted = true;

      // stop here if form is invalid
      if (this.myForm.invalid) {
        console.log(this.myForm)
        return;
      }

      console.log("this.myForm.value", this.myForm.value);
      
  }

}

Here is my html page.

<!-- Spinner -->
<ngx-spinner></ngx-spinner>

<section id="profile-form" class="bg-grey">
    <div class="container">
      <div class="row justify-content-center">
        <div class="col-lg-10 col-md-12">
          
          <h1 class="text-center">Update your profile</h1>

          <div class="form p-md-6">

              
              <form  [formGroup]="myForm" (ngSubmit)="onSubmit()">

                <div class="form-row">
                    <div class="form-group d-none">
                        <input type="text"  formControlName="userid" value={{userid}}>
                    </div>
                    <div class="form-group col-md-6">
                        <label for="linkedin">First Name</label>
                        <input type="text" class="form-control" formControlName="first_name" placeholder="First Name">
                    </div>
                    <div class="form-group col-md-6">
                        <label for="lastname">Last Name</label>
                        <input type="text" class="form-control" formControlName="last_name" placeholder="Last Name">
                    </div>
                </div>

                <div class="form-row">
                    <div class="form-group col-md-6">
                        <label for="linkedin">Email ID</label>
                        <input type="email" class="form-control" formControlName="email" placeholder="Email ID">
                    </div>
                    <div class="form-group col-md-6">
                        <label for="lastname">Cellphone Number</label>
                        <input type="text" class="form-control" formControlName="mobile" placeholder="Cellphone Number" [ngClass]="{ 'is-invalid': submitted && f.mobile.errors }" required>
                        <div *ngIf="submitted && f.mobile.errors" class="invalid-feedback">
                            <div *ngIf="f.mobile.errors.required">This field is required</div>
                        </div>
                    </div>
                </div>

                

                  
                  <div class="form-row">
                      <div class="button-group-pills text-center col-md-12" data-toggle="buttons">

                        <label class="btn btn-default" *ngFor="let skill of skills">
                            <input type="checkbox" formArrayName="skills" (change)="onCheckboxChange($event)" value={{skill.id}} [ngClass]="{ 'is-invalid': submitted && f.skills.errors }" required>
                            <div>{{skill.skill}}</div>
                        </label>
                        <div *ngIf="submitted && f.skills.errors" class="error">
                            <div *ngIf="f.skills.errors.required">This field is required</div>
                        </div>
                      </div>
                      
                  </div>



                  <div class="form-row justify-content-center text-center pt-4 pb-2">
                      <div class="col-md-8">
                          <button type="submit" class="btn btn-apply px-4">save profile</button>
                      </div>
                  </div>
              </form>
          </div>
              
        </div>

      </div>
    </div>
  </section>

Please help .........................................................................................................................................................................................................................................................................

Sadique AMT
  • 25
  • 1
  • 9

2 Answers2

2

You toggle [checked] value by checking if the current value is in the checkArray array

Include this in your input field

[checked]="checkArray.includes(skill.id)"

So your input becomes

    <input type="checkbox" formArrayName="skills" (change)="onCheckboxChange($event)" [checked]="checkArray.includes(skill.id)
 value={{skill.id}} [ngClass]="{ 'is-invalid': submitted && f.skills.errors }" required>

UPDATE

The above would work if you're pushing only the id of the skill into the array. But since you are pushing the entire skill object you can check for the object instead.

[checked]="checkArray.includes(skill)"

   <input type="checkbox" formArrayName="skills" (change)="onCheckboxChange($event)" [checked]="checkArray.includes(skill)
 value={{skill.id}} [ngClass]="{ 'is-invalid': submitted && f.skills.errors }" required>
crazychukz
  • 676
  • 1
  • 4
  • 10
  • not working... My checkArray structure is look like this, ` CheckedArray = [ 0: { id: 1, skill: "item1" }, 1: { id: 2, skill: "item2" }, ] ` – Sadique AMT Nov 27 '20 at 08:58
  • I have updated the answer to suit your condition. Let me if that works, if it doesn't I can show you a solution using pipe instead. Cheers – crazychukz Nov 27 '20 at 09:57
  • it's showing ERROR TypeError: Cannot read property 'includes' of undefined – Sadique AMT Nov 27 '20 at 10:19
  • Oh I see that your array variable is static and is cleared every time you the check box changes. You can declare checkArray before the constructor like so `checkArray: any = []` and then in your `onCheckboxChange(e)` func then call `this.checkArray` instead of declaring a const `checkArray`. Let me know if this is clear – crazychukz Nov 27 '20 at 12:44
1

Sadique, I suppose you want that your "skills" was an array of values. I don't find the SO where I used ngModel inside a ReactiveForms to mannage a list of checkBox. The most closer is this another SO

The idea is that you has NOT a FormArray, just a FormControl, and you use [(ngModel)] to give value to the formControl. yes a FormControl can store an Array, and yes a FormControl exist even you has no input in .html

    <label class="btn btn-default" *ngFor="let skill of skills">
       <input type="checkbox" 
          [ngModelOptions]="{standalone:true}"
          <!--see that "is checked" if in the array you has the value-->
          [ngModel]="(myForm.get('skills').value || []).indexOf(skill.id)>=0" 
          <!--when change, we call to the function-->
          (ngModelChange)="onChange($event,skill.id)" >
           <div>{{skill.skill}}</div>
    </label>

And

  onChange(checked: boolean, id: number) {
    
    const control = this.myForm.get("skills"); //get the control
    let value = control.value || [];       //get the value, if null an empty array
    if (checked && value.indexOf(id) < 0)  //if we checked and it's not in the array
      value = [...value, id].sort((a, b) =>    //concatenate the value and sort
        this.skills.findIndex(f => f.id == a) >
        this.skills.findIndex(f => f.id == b)? 1: -1
      );
    if (!checked) value = value.filter(x => x != id);  //if not checked remove it

    control.setValue(value.length ? value : null);  //finally set value
                          //see that is nothing selected, give value null
                          //this make that we can use Validators.required
  }

See the stackblitz

Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • Thanks for your answer... My actual issue is, I have to make my checkboxes as checked dynamically... If anyone selected 2 items and saved, then it should checked all time... I expecting you got issue.. Thanks – Sadique AMT Nov 27 '20 at 10:43
  • when you create the Control you can give value, e.g. `myForm.get('skills').setValue([1,3])`, or when you create the form control:`myForm=new FormGroup({skill:new FormControl([1],Validators.required})`. If in your "profile" the value of "skills" is an array, should work your `this.myForm.patchValue(this.profile);` what's the value or your "profile"? – Eliseo Nov 27 '20 at 10:51