复选框被选中,但它们在页面重新加载时没有初始值

Checkboxes are checked but they have no initial value on page reload

当我 check/uncheck 个框并提交到服务器时,当前设置工作正常。

然而,当页面重新加载或当我去编辑时,页面加载正常并且复选框正在检查正确的条目,就像这样...

这里的问题是当我点击提交而不触及任何值时,提交的数组是空的 permission_ids: [],需要再次点击它们才能触发 OnChange() 而我不能当我加载页面时自动执行此操作,因为我是 Angular

的新手

据我了解,这里的问题是选中了复选框,但未更新表单的值。

这是代码

模板

<h4>Permissions</h4>
            <div class="form-group row p-t-20">
              <div class="col-sm-4">
                <div class="custom-control custom-checkbox" *ngFor="let perm of permissions; let i=index">                
                  <input
                    type="checkbox"
                    class="custom-control-input"
                    id="permission_{{perm.id}}"
                    [value]="perm.id"
                    (change)="onPermissionCheckboxChange($event)"
                    [checked]="permissionExists(perm.id)">
                  <label
                    class="custom-control-label"
                    for="permission_{{perm.id}}">
                    {{ perm.name }}
                  </label>
                </div>
              </div>
            </div>

TS

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormArray, FormControl, Validators  } from "@angular/forms";
import { NotificationService } from "../../notification/notification.service";
import { PermissionsService } from "../../permissions/permissions.service";
import { HttpClient } from "@angular/common/http";
import { environment } from "../../../../environments/environment";
import { Router, ActivatedRoute } from "@angular/router";
import { RolesService } from "../roles.service";

@Component({
  selector: 'app-edit-role',
  templateUrl: './edit-role.component.html',
  styleUrls: ['./edit-role.component.css']
})
export class EditRoleComponent implements OnInit {
  isLoading: boolean = false;
  roleId: number = +this.route.snapshot.params['id']
  roleObj: any = {};
  haveRole: any = true;
  roles: any;
  role: any;

  permissions: any;

  form: FormGroup;

  constructor(
    private http: HttpClient,
    private router: Router,
    private route: ActivatedRoute,
    private fb: FormBuilder,
    private notificationService: NotificationService,
    private rolesService: RolesService,
    private permissionsService: PermissionsService
  ) {
    this.form = this.fb.group({
      role: new FormGroup({
        name: new FormControl('', [Validators.required]),
        permission_ids: this.fb.array([])
      })
    })
  }

  permissionExists(id: number) {
    return this.role.permissions.find(function(el: any){ return el.id === id }) !== undefined;
  }

  ngOnInit(): void {
    this.rolesService.getRoles().subscribe(response => {

    this.roles = response.body;
    this.role = this.roles.find((el: any) =>  el.id === this.roleId)

    //console.log(this.role);
    this.isLoading = false;
    this.form.patchValue({
      'role': {
        'name': this.role.name
      }
    });
    },
    error => {
      this.isLoading = false;
      this.notificationService.showNotification(
        error.error.title,
        error.error.details,
        'error'
      );
    })

    
    this.permissionsService.getPermissions().subscribe(response => {

      this.permissions = response.body;
      this.isLoading = false;
    },
    error => {
      this.isLoading = false;
      // console.log(error.error);
      this.notificationService.showNotification(
        error.error.title,
        error.error.details,
        'error'
      );
    })
  }


  onPermissionCheckboxChange(e: any) {
    const checkArray: FormArray = this.form.get('role.permission_ids') as FormArray;
if (e.target.checked) {
      checkArray.push(new FormControl(e.target.value));
    } else {
      let i: number = 0;
      checkArray.controls.forEach((item: any) => {
        if (item.value == e.target.value) {
          checkArray.removeAt(i);
          return;
        }
        i++;
      });
    }
  }

  onSubmit() {
    this.roleObj.role = this.form.value.role
    console.log(this.roleObj)
  }
}

请原谅我糟糕的代码,但我仍在学习 angular 因为我主要 Ruby 在 Rails 开发人员

阿米尔,你的代码有点混乱。 (此外,您还混合了 FormBuilder 和 FormControl 的构造函数)

先想对象,后创建表单。我想你的“角色”就像,例如

{
  name:'name',
  permissions:[1,3]
}

还有你的权限和数组

[{id:1,name:"Can create category"},{id:2,name:"Can read category}...]

Angular 中的输入类型“checkbox”只有两个值:true 或 false,因此如果您使用 FormArray,其值将是例如[true,false,true,false,false]

所以一种方法可以创建一个 FormGroup,例如

  form = new FormGroup({
    name: new FormControl(this.role.name, [Validators.required]),
    permissions: new FormArray(
      this.permissions.map(
        x => new FormControl(this.role.permissions.find(p => p == x.id) != null)
      )
    )
  });

要管理,请创建一个 getter rolePermision,return formArray

get rolePermision()
{
    return this.form.get('permissions') as FormArray
}

还有一个html喜欢

<form [formGroup]="form">
   <input formControlName="name">
   <div formArrayName="permissions">
     <div *ngFor="let control of rolePermision.controls;let i=index">
      <input 
            [formControlName]="i" type="checkbox">{{permissions[i].name}}
            </div>
   </div>
</form>

然后,提交后

submit(form: FormGroup) {
    if (form.valid) {
      const data = {
        name: this.form.value.name,
        permisions: this.permissions
          .filter((x, index) => form.value.permissions[index])
          .map(x => x.id)
      };
      ...use data to send to your service..
    }
  }

另一种方法是让一个 formGroup 有两个 formControl,其中一个存储一个数组

  form = new FormGroup({
    name: new FormControl(this.role.name, [Validators.required]),
    permissions:new FormControl(this.role.permissions)
  })

并使用 [ngModel] 和 (ngModelChange)

<form [formGroup]="form">
  <input formControlName="name">
  <div *ngFor="let permision of permissions">
    <input type="checkbox" [ngModel]="form.get('permissions')?.value && form.get('permissions').value.indexOf(permision.id)>=0"
    [ngModelOptions]="{standalone:true}"
    (ngModelChange)="change(permision.id,$event)"
    >{{permision.name}}
    </div>
  
</form>

功能变化如

  change(id: any, checked: boolean) {
    const oldValue = this.form.value.permissions;
    const permissions = checked
      ? this.permissions.filter(
          x => (oldValue && oldValue.indexOf(x.id) >= 0) || x.id == id
        )
      : this.permissions.filter(
          x => oldValue && oldValue.indexOf(x.id) >= 0 && x.id != id
        );

    this.form
      .get('permissions')
      .setValue(permissions.length > 0 ? permissions.map(x => x.id) : null);
  }

您可以在this stackblitz

中获得两种方法