我正在创建一个动态表单,它使用来自后端的json响应来呈现一个反应性表单。
所以json反应的一个例子是..。
"controls": [
{
"name": "name",
"label": "Name",
"value": "",
"type": "text",
"validators": {
"required": true,
"minLength": 4
}
},
]
}然后,ts文件使用formGroup构建formBuilder。但是,我在添加一个formControl复选框数组时遇到了问题.其中一个复选框必须选中,否则表单将无效。所以json看起来..。
{
"controls": [
{
"title": "Which of these items do you want to buy? Check as many as you'd like",
"name": "items",
"checkboxOptions": [
{
"value": "",
"label": "Item 1",
"name": "item1"
},
{
"value": "",
"label": "Item 2",
"name": "item2"
}
],
"type": "checkboxgroup",
"validators": {
"required": true
}
}
]
}我可以成功地添加checkboxgroup,因为它是自己的表单组,它有一个表单控件数组。然后我可以将formGroup添加到父formGroup中..。但是我对嵌套formGroup的html部分有问题。
顺便说一句。这就是文本框的呈现方式。
<form [formGroup]='myForm' (keydown.enter)="$event.preventDefault()" novalidate>
<div *ngFor='let control of formControl.controls'>
<mat-form-field appearance="outline">
<mat-label>{{ control.label }}</mat-label>
<input matInput [formControlName]='control.name' [type]='control.type'>
</mat-form-field>
</div>
</form>但我不知道如何使用它自己的验证器来呈现formControl复选框数组。谢谢
发布于 2022-07-12 10:49:10
您可以创建一个组件,用于存储数组的FormControl。
有些人喜欢
@Component({
selector: 'mat-checkbox-group',
template: `
<span [class.horizontal]="horizontal">
<ul>
<li *ngFor="let item of list">
<mat-checkbox [ngModel]="control.value &&
control.value.indexOf(item.value)>=0"
(ngModelChange)="update($event,item.value)">
{{item.text}}
</mat-checkbox>
</li>
</ul>
</span>
`,
styles: [
`
ul{
padding:0;
list-style: none;
}
.horizontal li{
display:inline-block;
margin-right:.5rem;
}
`,
],
})
export class CheckboxGroup {
list: { value: string | number; text: string }[];
control: FormControl;
keys: any;
log: any;
horizontal:boolean
constructor(@Optional() @Attribute('horizontal') _horizontal:any){
this.horizontal=_horizontal!==undefined && _horizontal!==null?
_horizontal!=="false":false
}
@Input('control') set _control(value: any) {
this.control = value as FormControl;
}
@Input('source') set _source(value: any[]) {
const type = typeof value[0];
if (type == 'string' || type == 'number')
this.list = value.map((x) => ({ value: x, text: '' + x }));
else {
const match = [
...JSON.stringify(value[0])
.replace(/\"/g, '')
.matchAll(/(\w+)\:[^,]*/g),
].map((x) => x[1]);
this.list = value.map((x) => ({ value: x[match[0]], text: x[match[1]] }));
}
}
update(checked: boolean, value: string | number) {
const oldValue = this.control.value || [];
if (!checked)
this.control.setValue(
oldValue.filter((x: string | number) => x != value)
);
else
this.control.setValue(
this.list
.filter(
(x: any) => x.value == value || oldValue.indexOf(x.value) >= 0
)
.map((x) => x.value)
);
}
}允许你写
<mat-checkbox-group [source]="control.checkboxOptions"
[control]="myform.get(control.name)" >
</mat-checkbox-group>小心地,组件允许一个字符串数组、一个对象数组的数字数组作为“源”。第一个属性是值,第二个属性是复选框的标签。
请参阅stackblitz
更新我们可以避免创建新组件,但在本例中,.html如下所示
<div *ngFor="let control of controlsJson?.controls">
<div class="form-title">{{ control.title }}</div>
<div class="bottom-space" *ngIf="control.type === 'checkboxgroup'">
<ng-container *ngIf="dynamicForm.get(control.name) as ctrl">
<div *ngFor="let item of control.checkboxOptions">
<mat-checkbox
[ngModel]="ctrl.value && ctrl.value.indexOf(item.value) >= 0"
(ngModelChange)="
update($event, item.value, control.checkboxOptions, ctrl)
"
[ngModelOptions]="{ standalone: true }"
>
{{ item.label }} {{ item.value }}
</mat-checkbox>
</div>
</ng-container>
</div>
</div>我们使用
<ng-container *ngIf="dynamicForm.get(control.name) as ctrl">避免重复dynamicForm.get(control.name)
确保我们使用的是ngModel -这不是班纳纳新税
[ngModel]="ctrl.value && ctrl.value.indexOf(item.value) >= 0"要控制,我们的更新需要作为参数
函数更新非常类似于我们有组件时。
update(checked: boolean, value: string | number,options:any[],control:any) {
const oldValue = control.value || [];
if (!checked)
control.setValue(
oldValue.filter((x: string | number) => x != value)
);
else
control.setValue(
options
.filter(
(x: any) => x.value == value || oldValue.indexOf(x.value) >= 0
)
.map((x) => x.value)
);
}但要小心!
我们只有一个uniq FormControl
for (const control of this.controlsJson.controls) {
if (control.type == 'checkboxgroup') {
this.dynamicForm.addControl(
control.name,new FormControl())
}
}当我们定义“选项”时,每个选项的“价值”应该是不同的。
"checkboxOptions": [
{
"value": "false", //<--this value will be store
"label": "Item 1",
"name": "item1"
},
{
"value": "true", //<--this value will be store
"label": "Item 2",
"name": "item2"
}
],如果我们想要“至少一个”,那么在创建Validators.required时只需要添加FormControl。更好的是,我们创建一个函数,返回一个基于字符串数组的验证器数组。
想象一下有些人
"validators": ["required","max(3)"]我们可以做一个函数
getValidators(validators:string[])
{
return validators.map(x=>{
if (x=="required")
return Validators.required;
if (x.substr(0,3)=="max")
{
const max=x.match(/max\((\d+)\)/)
return Validators.max(+max[1])
}
....
return null //<--if some string not fullfilled any "if"
}).filter(x=>x)
}写一些类似的东西
for (const control of this.controlsJson.controls) {
if (control.type == 'checkboxgroup') {
this.dynamicForm.addControl(
control.name,new FormControl(null,this.getValidators(control.validators)))
}
}https://stackoverflow.com/questions/72941882
复制相似问题