如何使用 angular2 Reactive 表单构建嵌套数组?

Posted

技术标签:

【中文标题】如何使用 angular2 Reactive 表单构建嵌套数组?【英文标题】:How to build nested array by using angular2 Reactive forms? 【发布时间】:2017-08-29 12:51:57 【问题描述】:
I have an array like 
[  
     
      "PermissionRoleModule":  
         "id":1,
         "legend":"businessModule",
         "group":[  
              
               "PermissionRoleGroup":  
                  "id":1,
                  "permission":  
                     "controleType":"ff",
                     "id":2,
                     "key":"create Business"
                  ,
                  "roles":[  
                       
                        "id":1,
                        "name":"self"
                     ,
                       
                        "id":2,
                        "name":"other"
                     
                  ]
               
            ,
              
               "PermissionRoleGroup":  
                  "id":1,
                  "permission":  
                     "controleType":"ff",
                     "id":2,
                     "key":"edit business"
                  ,
                  "roles":[  
                       
                        "id":1,
                        "name":"self"
                     ,
                       
                        "id":2,
                        "name":"other"
                     
                  ]
               
            
         ]
      
   ,
     
      "PermissionRoleModule":  
         "id":2,
         "legend":"PanicModule",
         "group":[  
              
               "PermissionRoleGroup":  
                  "id":1,
                  "permission":  
                     "controleType":"ff",
                     "id":2,
                     "key":"create panic"
                  ,
                  "roles":[  
                       
                        "id":1,
                        "name":"self"
                     ,
                       
                        "id":2,
                        "name":"other"
                     
                  ]
               
            ,
              
               "PermissionRoleGroup":  
                  "id":1,
                  "permission":  
                     "controleType":"ff",
                     "id":2,
                     "key":"edit panic"
                  ,
                  "roles":[  
                       
                        "id":1,
                        "name":"self"
                     ,
                       
                        "id":2,
                        "name":"other"
                     
                  ]
               
            
         ]
      
   
]

我的观点如附件中所示

当我点击提交按钮时,我期待 json 像

[  
     
      "name":"aaa",
      "description":"das",
      "permission":[  
           
            "permission_id":1,
            "relation":2
         
      ]
   
]

如何使用响应式表单为此案例构建表单组

我试过这样

component.ts

roleForm: FormGroup;
  formField: any;
validateForm() 
this.formField['rolename'] = new FormControl('', Validators.compose([Validators.required]))
this.formField['roledescription'] = new FormControl('', Validators.compose([Validators.required]))

this.form_objects.forEach(element => 
  if (element.group) 
    element.group.forEach(PermissionRoleGroup => 
      this.formField[PermissionRoleGroup.permission.key] = new FormControl(value:'', Validators.compose([Validators.required]))

      if (PermissionRoleGroup.roles) 
        PermissionRoleGroup.roles.forEach(role => 
          this.formField[role.key] = new FormControl('', Validators.compose([Validators.required]))
        );
      

    )
  
);

this.roleForm = this.fb.group(this.formField);
 

html

   <div  class="form-row" *ngFor="let element of form_objects; let i = index; ">

              <table  class="table table-bordered">
                <tr *ngFor="let permissionRoleGroup of element.group;let j= index;">
                  <table class="table table-bordered" style="margin-bottom: 0px;">
                    <td >
                      <label class="font-light">
                        <input type="checkbox"

                               [id]="permissionRoleGroup.permission.key"
                               [formControlName]="permissionRoleGroup.permission.key"
                               [value] = "permissionRoleGroup.permission.value">
                        permissionRoleGroup.permission.label -permissionRoleGroup.permission.ischecked
                      </label>
                    </td>

                    <td  *ngFor="let role of permissionRoleGroup.roles">
                      <label class="font-light">
                        <input   type="checkbox"

                                 [value] = "role.value"
                                 [formControlName]=" role.key">
                        role.label-role.ischecked
                      </label>
                    </td>
                  </table>
                </tr>
              </table>

            </div>

有了这个我可以构建表单,在提交过程中,我的表单没有创建 json。

这是plunker链接https://plnkr.co/edit/h2VuBw4uITi6czn98ViS?p=preview

因为我是 angular-2 的初学者,所以请帮帮我。

【问题讨论】:

可以分享模板吗? 我添加了html代码,请检查 如何填写form_objects?如果你提供 plunker 会很棒 我添加了plunk链接你可以检查一下 查看此链接。它有助于解决您的问题***.com/questions/43291346/… 【参考方案1】:

我创建了以下函数:

patchValue(form:any, object:any)

    var iterate = (mForm:any, mObject:any)=> 
        for (var key in mObject) 
            if (Array.isArray(mObject[key])) 
                if(mForm.value[key] == undefined || mForm.value[key] == null)
                    if(Array.isArray(mForm.value))
                        mForm.push(new FormArray([]));
                     else 
                        mForm.addControl(key, new FormArray([]));
                    
                
                iterate(mForm.controls[key], mObject[key]);
            
            else if (typeof mObject[key] == 'string' || typeof mObject[key] == 'number' || typeof mObject[key] == 'boolean' || mObject[key] == null) 
                if(mForm.value[key] == undefined || mForm.value[key] == null)
                    if(Array.isArray(mForm.value))
                        mForm.push(new FormControl(''));
                     else 
                        mForm.addControl(key, new FormControl(''));
                    
                
            
            else if (mObject[key] != null && typeof mObject[key] == 'object') 
                if(mForm.value[key] == undefined || mForm.value[key] == null)
                    if(Array.isArray(mForm.value))
                        mForm.push(new FormGroup());
                     else 
                        mForm.addControl(key, new FormGroup());
                    
                

                iterate(mForm.controls[key], mObject[key]);
            
            else 
                console.log(key);
                console.log('undefined element');
            
        
    ;

    iterate(form, object);

    form.patchValue(object);

只需传递一个空表单和您的对象。它将根据您传递的对象构建您的表单:

this.form = this.fb.array([]);
this.template = [  
     
      "PermissionRoleModule":  
         "id":1,
         "legend":"businessModule",
         "group":[  
              
               "PermissionRoleGroup":  
                  "id":1,
                  "permission":  
                     "controleType":"ff",
                     "id":2,
                     "key":"create Business"
                  ,
                  "roles":[  
                       
                        "id":1,
                        "name":"self"
                     ,
                       
                        "id":2,
                        "name":"other"
                     
                  ]
               
            ,
              
               "PermissionRoleGroup":  
                  "id":1,
                  "permission":  
                     "controleType":"ff",
                     "id":2,
                     "key":"edit business"
                  ,
                  "roles":[  
                       
                        "id":1,
                        "name":"self"
                     ,
                       
                        "id":2,
                        "name":"other"
                     
                  ]
               
            
         ]
      
   ,
     
      "PermissionRoleModule":  
         "id":2,
         "legend":"PanicModule",
         "group":[  
              
               "PermissionRoleGroup":  
                  "id":1,
                  "permission":  
                     "controleType":"ff",
                     "id":2,
                     "key":"create panic"
                  ,
                  "roles":[  
                       
                        "id":1,
                        "name":"self"
                     ,
                       
                        "id":2,
                        "name":"other"
                     
                  ]
               
            ,
              
               "PermissionRoleGroup":  
                  "id":1,
                  "permission":  
                     "controleType":"ff",
                     "id":2,
                     "key":"edit panic"
                  ,
                  "roles":[  
                       
                        "id":1,
                        "name":"self"
                     ,
                       
                        "id":2,
                        "name":"other"
                     
                  ]
               
            
         ]
      
   
]
this.patchValue(this.form, this.template);

如果你想自己构建它,你必须手动进行......我会推荐你​​这篇文章:https://blog.thoughtram.io/angular/2016/06/22/model-driven-forms-in-angular-2.html

【讨论】:

谢谢,但是如果你在 plunker 中添加这个对我来说会更好,我在上面添加了一个 plunk 链接,你能用你的解决方案修改吗, @ncohen 能否提供html @SoumyaGangamwar html 取决于您的模板 是的,我的意思是说上面注释代码的任何 plunker 示例,我都能正确理解【参考方案2】:

我会创建一些像 permissionGroups 这样的属性并展平你的数据

permissionGroups: any[];
...
this.permissionGroups = this.form_objects
   .reduce((acc, permission) => [...acc, ...permission.group], []);

然后我会像这样构建formGroup

const permissions = this.permissionGroups.map(group => 
  return this.fb.group(
    [group.permission.key]: false,
    roles: this.fb.array(group.roles.map(role => this.fb.control(false)))
  );
);

this.roleForm = this.fb.group(
  roleName: ['', Validators.required],
  roleDescription: ['', Validators.required],
  permissions: this.fb.array(permissions)
);

并准备html如下:

<form [formGroup]="roleForm" (submit)="submit(roleForm.value)">
    <div class="form-group">
        <label>Name</label>
        <input type="text" class="form-control" formControlName="roleName">
    </div>
    <div class="form-group">
        <label>Description</label>
        <textarea rows="4" class="form-control" formControlName="roleDescription"></textarea>
    </div>          

    <div formArrayName="permissions">
      <div class="form-row" *ngFor="let permission of roleForm.controls.permissions.controls; let i = index; ">
         <table [formArrayName]="i">
            <tr>
              <table>
                <tr>
                    <td>
                      <label class="font-light">
                        <input type="checkbox" [formControlName]="permissionGroups[i].permission.key">
                         permissionGroups[i].permission.key 
                      </label>
                    </td>
                    <td *ngFor="let role of permission.controls.roles.controls; let j = index;">
                      <label class="font-light" formArrayName="roles">
                        <input type="checkbox" [formControlName]="j">    
                         permissionGroups[i].roles[j].name          
                      </label>
                    </td>
                </tr>
            </table>
        </tr>
      </table>
    </div>
  </div>
  <button type="submit">Submit</button>
</form>

当您提交表单时,您需要将表单值转换为您想要的结果,如下所示:

submit(value) 
  this.result = Object.assign(, value, 
    permissions: value.permissions
      .reduce((acc, permission, idx) => 
        return permission[this.permissionGroups[idx].permission.key] ?
          [
            ...acc,
            
              permission_id: this.permissionGroups[idx].permission.id,
              relation: permission.roles
                .reduce((rolesAcc, role, roleIdx) => 
                  return role ? [...rolesAcc, this.permissionGroups[idx].roles[roleIdx].id] : rolesAcc;
                , [])
            
          ] : acc
      , [])
  );

你会看到如下输出:


  "roleName": "",
  "roleDescription": "",
  "permissions": [
    
      "permission_id": 2,
      "relation": [
        1
      ]
    ,
    
      "permission_id": 2,
      "relation": [
        1,
        2
      ]
    
  ]

你可以玩Plunker Example

中的代码

另见

https://netbasal.com/handling-multiple-checkboxes-in-angular-forms-57eb8e846d21

【讨论】:

@yuzui 非常感谢, @SoumyaGangamwar developer.mozilla.org/en/docs/Web/javascript/Reference/… 好的,上面代码中的 [...rolesAcc, (...) 是什么意思,(...) developer.mozilla.org/en/docs/Web/JavaScript/Reference/… @yuzui 我有一个类似“其他”的概念,正如我之前在我的问题中提到的那样。另一方面,我还有一个 json 部分,应该像这样:“roleName”:“dfd”,“roleDescription”:“dfdf”,“permissions”:[“permission_id”:2,“relation”:1,“ otherrole":[ "roleid":2, "status":1 ] ]

以上是关于如何使用 angular2 Reactive 表单构建嵌套数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular 世界之外发生更改时更新 Angular 2 Reactive 表单字段

如何使用 Reactive Forms (Angular2 RC3) 进行异步验证?

Angular 2 Reactive Forms 复选框 - 将 Bool 绑定到数字

Angular 2 Reactive Forms 问题如何以角度方式而不是 jquery 方式进行

如何检测 Angular 2 反应/动态表单的一个元素发生的变化?

如何在提交按钮表单中使用路由 - Angular2