2

I'm creating a complex template-driven form with Angular 2 which get's its structure of groups and fields from an API. The API sends a JSON object containing groups that can contain fields and / or sub-groups. Since the groups can have sub-groups, I think the simplest way to handle this is to have a custom control, FieldGroupComponent, which takes an input parameter "Group", and if the Group contains sub-groups, it will render those recursively, using a FieldGroupComponent.

The problem I'm having is that the ngForm doesn't recognize the input controls in the FieldGroupComponent as FormControls. The ngForm thinks it doesn't have any controls, and won't recognize that the fields are invalid.

The form page looks something like this:

<form ngForm (ngSubmit)="submitForm()">
  <field-group *ngFor="let group of FormGroups" [group]="group"></field-group>
</form>

And the FieldGroupComponent:

@Component({
  selector: "field-group",
  templateUrl: "./field-group.component.html"
})
export class FieldGroupComponent {
  @Input("group") group;
}

And the FieldGroupComponent template:

<fieldset>
  <h1>{{group.Title}}</h1>
  <div *ngFor="let field of group.Fields">
    ... render field ...
  </div>
  <div *ngFor="let subGroup of group.FieldGroups">
    <field-group [group]="subGroup"></field-group>
  </div>
</fieldset>
2

2 Answers 2

1

I ended up simply passing the NgForm into the FieldGroupComponent as an @Input, and manually adding the field controls to the form:

@Input("form") form: NgForm;
@ViewChildren(NgModel) private formControls: QueryList<NgModel>;

ngAfterViewInit(): void {
  this.formControls.forEach((item: NgModel) => this.form.addControl(item));
}
Sign up to request clarification or add additional context in comments.

1 Comment

Did this work? How did you implement validation i.e. how the form knows if for example required inputs are filled or not?
0

My form was dynamic so I extended SZH's solution ngAfterViewInit so formControls are rebuild on every change. M

Might cause some perfomance penalties in some cases, but if you need it it keeps form controls updated:

public ngAfterViewInit(): void {
    this._formControls.changes.subscribe(() => {
        this._formControls.forEach((item: NgModel) => {
            if (!this.form.controls[item.name]) {
                this.form.addControl(item);
            }
        });
    });
}

Comments

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.