问题
I am making angular 6 application where i am using Angular dynamic form
Here i have made a nested input fields in which there will be two input textboxes at the initial stage and on click the add button the next two input boxes will get append on each click on add button.
Everything works fine here regarding it..
Here i have used the values in question-service.ts as,
new TextboxQuestion({
elementType: "textbox",
class: "col-12 col-md-4 col-sm-12",
key: "project_name",
label: "Project Name",
type: "text",
value: '',
required: true,
order: 1
}),
new TextboxQuestion({
elementType: "textbox",
class: "col-12 col-md-4 col-sm-12",
key: "project_desc",
label: "Project Description",
type: "text",
value: '',
required: true,
order: 2
}),
new ArrayQuestion({
key: 'myArray',
value: '',
order: 3,
children: [
new TextboxQuestion({
elementType: "textbox",
class: "col-12 col-md-4 col-sm-12",
key: "property_one",
label: "Property One",
type: "text",
value: '',
required: true,
order: 3
}),
new TextboxQuestion({
elementType: "textbox",
class: "col-12 col-md-4 col-sm-12",
key: "property_two",
label: "Property Two",
type: "text",
value: '' ,
required: true,
order: 4
})
]
})
Which i need to change like the data should be from json for each like,
jsonData: any = [
{
"elementType": "textbox",
"class": "col-12 col-md-4 col-sm-12",
"key": "project_name",
"label": "Project Name",
"type": "text",
"value": "",
"required": true,
"order": 1
},
{
"elementType": "textbox",
"class": "col-12 col-md-4 col-sm-12",
"key": "project_desc",
"label": "Project Description",
"type": "text",
"value": "",
"required": true,
"order": 2
},
{
"elementType": "array",
"key": "myArray",
"value": "",
"order": "3",
"children": [
{
"elementType": "textbox",
"class": "col-12 col-md-4 col-sm-12",
"key": "property_one",
"label": "Property One",
"type": "text",
"value": "",
"required": true,
"order": 3
},
{
"elementType": "textbox",
"class": "col-12 col-md-4 col-sm-12",
"key": "property_two",
"label": "Property Two",
"type": "text",
"value": "",
"required": true,
"order": 4
}
]
}
];
Stackblitz without JSON:
https://stackblitz.com/edit/angular-x4a5b6-xcychx
Stackblitz with JSON:
https://stackblitz.com/edit/angular-x4a5b6-u6ecpk
The same scenario which happens in stacblitz link without json needs to happen while loading JSON..
I have given the following inside getQuestions()
like,
getQuestions() {
console.log(this.jsonData);
let questions: any = [];
this.jsonData.forEach(element => {
if (element.elementType === 'textbox') {
questions.push(new TextboxQuestion(element));
} else if (element.elementType === 'array') {
questions.push(new ArrayQuestion(element));
}
});
return questions.sort((a, b) => a.order - b.order);
}
}
For normal textbox its working but whereas for the children its not working on clicking add button (textboxes were not displayed), the child textboxes not getting added.
Kindly help me to achieve the same result that happens in link 1 also needs to happen while using JSON in link 2 .. And also kindly dont include any third party libraries inside everything is going in core angular.
回答1:
@Many, when you have type array, you must create the children before push the array.
...
} else if (element.elementType === 'array') {
let children:any[]=[]; //declare children
//each children of element fill our array children
element.children.forEach(e=>{
if (e.elementType === 'textbox') {
children.push(new TextboxQuestion(e));
}
})
//Hacemos un push not of element else element + the property children
//changed (it will be the array created)
questions.push(new ArrayQuestion({...element,children:children}));
}
回答2:
You must add a new type "check-box"
export class CheckBoxQuestion extends QuestionBase<string> {
controlType = 'checkbox';
type: boolean;
constructor(options: {} = {}) {
super(options);
}
}
And change the dinamic Form question
<div [formGroup]="form">
<!--the label only show if it's NOT a checkbox --->
<label *ngIf="question.controlType!='checkbox'" [attr.for]="question.key">{{question.label}}</label>
<div [ngSwitch]="question.controlType">
...
<!--add type checkbox-->
<ng-container *ngSwitchCase="'checkbox'">
<input [formControlName]="question.key" type="checkbox"
[id]="question.key" >
<label [attr.for]="question.key">{{question.label}}</label>
</ng-container>
...
</div>
And question service to take account the new checkbox
else if (e.elementType === 'checkbox') {
children.push(new CheckBoxQuestion(e));
}
Update if we want to add more validators, take a look at the function "toFormGroup" of question.service.ts
toFormGroup(questions: QuestionBase<any>[]) {
let group: any = {};
questions.forEach(question => {
if (question.controlType=="array") {
group[question.key]=new FormArray([]);
}
else {
//create an array of "validators"
let validators:any[]=[];
//If question.required==true, push Validators.required
if (question.required && question.controlType!='checkbox')
validators.push(Validators.required);
//...add here other conditions to push more validators...
group[question.key] = new FormControl(question.value || '',validators);
}
});
return new FormGroup(group);
}
Update two it's necesary change too the questionbase.ts to add this properties
export class QuestionBase<T> {
value: T;
...
maxlength:number;
minlength:number;
constructor(options: {
value?: T,
....
minlength?:number,
maxlength?:number,
controlType?: string,
children?:any
} = {}) {
this.value = options.value;
....
this.minlength = options.minlength;
this.maxlength = options.maxlength;
...
}
}
For see the errors you must as about form.get(question.key).errors, e.g
<div class="errorMessage"
*ngIf="form.get(question.key).errors?.required">
{{question.label}} is required
</div>
Tip: for know about your errors use
{{form.get(question.key).errors|json}}
See the forked stackblitz
来源:https://stackoverflow.com/questions/53113962/form-element-values-as-json-using-angular-form