1

I am currently using Angular Reactive forms for a project - it is a dynamic form that cannot really be modeled since properties on it will change overtime. Right now it is a highly nested form that is built out containing as much as 4-5 levels deep.

Right now I have a main/outer FormGroup, that contains a FormArray of 'Scripts' that has properties and an FormArray of 'Questions'. Questions has properties with a FormArray of 'Fields'. Fields has properties as well as another FormArray of Options for those fields. Not all 'Fields' will have options such as single-line-text, but drop-down field would.

It gets a Document object from CosmosDB and iterates through this and basically builds the FormGroup out... My question is because this seems very messy, and I was curious to know if there was a better way to achieve this.

Here is a Document sample

"ScriptType": "Script", "Questions": [ { "Question": "What is the year, make and model of the vehicle your calling about?", "Type": "question", "Text": "", "Fields": [ { "PropertyName": "VehicleYear", "Label": "Year", "IsRequired": false, "Type": "drop-down", "HasOptions": false, "Options": [2001, 2002, 2003, ...] }, { "PropertyName": "VehicleMake", "Label": "Make", "IsRequired": false, "Type": "single-line-text", "HasOptions": false, "Options": [] }

Below is the Angular component that currently initializes the form...

initScript(script) {
const scriptGroup = this.fb.group({
  ScriptID: script.ScriptID || '',
  ScriptType: script.ScriptType,
  ScriptName: script.ScriptName,
  ScriptText: script.ScriptText,
  Questions: this.fb.array([])
});
const scriptControl = scriptGroup.get('Questions') as FormArray;
script.Questions.forEach(element => {
  scriptControl.push(this.initQuestion(element));
});
return scriptGroup;
}

initQuestion(script) {
const questionGroup = this.fb.group({
  Question: script.Question || '',
  Type: script.Type || '',
  Fields: this.fb.array([script.Fields] || []),
  IsVisible: script.IsVisible || true,
  Rules: [script.Rules] || []
});

const fieldControl = questionGroup.get('Fields') as FormArray;
script.Fields.forEach(element => {
  fieldControl.push(this.initField(element));
});

return questionGroup;

initField(script) {
return this.fb.group({
  PopertyName: script.PropertyName || '',
  PropertyName: script.PropertyName || '',
  Label: script.Label || '',
  Type: script.Type || '',
  Options: [script.Options] || []
});
}

There maybe hundreds of these over time so accessing these controls on the front end is somewhat cumbersome being so nested as well. Also, the response to these 'Questions' also needs to be saved as well once a new form is submitted. If anyone has any suggestions please let me know! Thanks

1 Answer 1

1

OK not sure if fully understand but see here example how dynamically create those fields. You could also generate them based on JSON loaded from back-end.

https://stackblitz.com/edit/angular-reactive-form-sobsoft

Sign up to request clarification or add additional context in comments.

1 Comment

please thanks for ur answer..do u know why i got this error after following the steps. Property 'controls' does not exist on type 'AbstractControl'. 30 *ngFor="let unit of exampleForm.controls.units.controls; let i=index"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.