如何使用 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 方式进行