1

I cant seem to find a proper example of how to fill a checkbox with values from an API when a form is in edit mode.

I have a service that fetches roles data from an API. Each role can have multiple permissions like edit-user, create-user, create-product, edit-product, etc. I want a form where a user can edit these role permissions using checkboxes. I have tried using patchValue as shown below but it doesnt respond to anything so far.

  rolePermissionList = [];
  permissionList = [];

  setupForm() {

    this.roleForm = this.fb.group({
      role_name: ["", Validators.required],
      description: [""],
      status: [""],
      permissions: this.fb.array([]),
    }, {updateOn: 'change'});

  }


  ngOnInit() {

    this.setupForm();

    this.route.paramMap.subscribe(params => {

      this.id = parseInt(params.get("id"));

      // fetch single role record
      this.getPageData(this.id);

    })

  }

  // get page data
  async getPageData(role_id) {

    this.spinner.show();

    // get role
    await this.getRole(role_id);

    // get all permissions
    await this.getPermissions();

    // get role permissions
    await this.getRolePermissions(role_id);

    this.spinner.hide();

  }

I have two services: one that returns the entire permissions list, and the other that returns permissions assigned to the current role. I want a way to check only permissions assigned to the current role being edited. These are the functions that fetch all permissions and rolepermissions:

// get permissions list

getPermissions() {

    this.permissionService.getPermissionsList()

      .subscribe(

        data => {

          console.log("permissions === ", data);

          this.permissionList = data;

        },

        error => console.log(error));

  }



  // get role permissions
  getRolePermissions(role_id?:any) {

    // if role_id is supplied
    let params = new HttpParams();
    if (role_id) {
      params=params.set('role_id', role_id.toString());
    }

    this.rolePermissionService.getRolePermissionsList(params)
      .subscribe(
        data => {

          // store fetched data
          this.rolePermissionList = data;

          // extract permission name from returned array
          var arrayOfPerms = data.map(function(obj) {
            return obj.name;
          });

          // patch data
          this.roleForm.pastchValue('permissions', arrayOfPerms);

        },
        error => {

          console.log(error);

        });

  }

The front end:

...

<div class="row" *ngIf="permissionList; else loading">

   <div *ngFor="let permission of permissionList; let i=index" class="col-md-6">

      <div class="custom-control custom-checkbox mr-sm-2 m-b-15">
         <input type="checkbox"
          [value]="permission.id"
          (change)="onCheckChange($event)"
          class="custom-control-input"
          id="checkbox-{{ i }}">

       <label class="custom-control-label" for="checkbox-{{ i }}">{{  permission.display_name }}</label>
      </div>

   </div>

</div>

...

Any help will be greatly appreciated?

1
  • Do you mind creating a Sample StackBlitz to work with? You can get the data from a json file in the assets folder via HttpClient. Just supply the url of /assets/data.json in the call to HttpClient's get method. Please share the link to the sample stackblitz. Or you could fork this stackblitz that I just created for this answer Commented Nov 1, 2019 at 8:37

2 Answers 2

2

I would change the setup a bit, and iterate a formarray in the template instead of permissionList. Also I would return the id:

var arrayOfPerms = data.map(function(obj) {
  return obj.id;
});

Since your permissionList is using the id as value.

So this is how the form would look before edit. Here I have omitted the http-request and hard coded the values:

permissionList = [
  { id: 1, displayName: 'Admin' },
  { id: 2, displayName: 'User' },
  { id: 3, displayName: 'SuperUser' }
];

rolePermissionList = [1, 3];

constructor(private fb: FormBuilder) {

  // set all checkboxes as false initially
  const ctrls = this.permissionList.map(control => this.fb.control(false));

  this.roleForm = this.fb.group({
    permissions: this.fb.array(ctrls),
  });
}

// for being able to shorten
get permissionsArr() {
  return this.roleForm.get('permissions') as FormArray;
}

submit() {
  // filter the checked and store in array
  const selectedRoles= this.roleForm.value.permissions
    .map((checked, i) => checked ? this.permissionList[i].id : null)
    .filter(value => value !== null);
  // here is an array of ids, e.g [1, 3]
  console.log(selectedRoles)
}

and the relevant template part:

<label formArrayName="permissions" *ngFor="let perm of permissionsArr.controls; index as i">
  <input type="checkbox" [formControlName]="i">
  {{permissionList[i].displayName}}
</label>

So when that is done, and you want to patch values, just call a function that checks which id's that match in permissionList, and use patchValue() on the form control:

patchValue() {
  this.permissionList.map((perm, i) => {
    if (this.rolePermissionList.indexOf(perm.id) !== -1) {
      this.permissionsArr.at(i).patchValue(true)
    }
  })
}

Here is a STACKBLITZ demo.

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

2 Comments

Thanks this worked for me with some minor changes. Cheers.
Great, awesome, glad I could help you on the way! :)
0

Patching or reseting form array is pretty annoying, you can check this article.

You need to update your array with the necessary length.

  • you can add or remove formControl in your array depending if you have more or less item when you want to patch the vaue.

2 Comments

Is it possible to patch an array of checkboxes in angular? I know this question must be having a simple answer, I just cant figure it out...
Yes you can. But your array need to have the correct length.

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.