Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Form in form. Can there be inheritance of form controls?

I have two components: ParentComponent and ChildComponent:

parent.component.ts

<form #form="ngForm" (ngSubmit)="onSubmit(form)" novalidate>
     <input type="text" name="firstControl" [(ngModel)]="firstControl" />
     <input type="text" name="secondControl" [(ngModel)]="secondControl" />
     <child-component>
</form>
{{form.value | json}}

child.component.ts

<input type="text" name="thirdControl" [(ngModel)]="thirdControl" />
<input type="text" name="fourthControl" [(ngModel)]="fourthControl" />

Now, {{form.value | json}} returns { "firstControl": "", "secondControl": "" } and it's clear. My question is: Is there a way to form enherit form controls from child component? What is the correct way to get { "firstControl": "", "secondControl": "", "thirdControl": "", "fourthControl": "" } for ParentComponent? Is it possible?

like image 600
Jaroslaw K. Avatar asked Sep 20 '17 13:09

Jaroslaw K.


People also ask

What is form inheritance?

Form inheritance enables you to create a base form and then inherit from it and make modifications while preserving whatever original settings you need. You can create subclassed forms in code or by using the Visual Inheritance picker.

How do you access a form control from another form?

A Form is a Control so we can cast any form in your project as a simple Control object. Example; Control c = TheForm("Form1"); Once we have this, we can gain access to ALL the child controls including the children in other container controls on the form.

How do you put controls on a form?

Position a control on the design surface of the Windows Forms Designer. In Visual Studio, drag the control to the appropriate location with the mouse. Select the control and move it with the ARROW keys to position it more precisely. Also, snaplines assist you in placing controls precisely on your form.

How do I inherit a Windows Form?

In order to inherit from a form, the file or namespace containing that form must have been built into an executable file or DLL. To build the project, choose Build from the Build menu. Also, a reference to the namespace must be added to the class inheriting the form.


1 Answers

Update:

Indeed there is an easier way:

import { FormsModule, ControlContainer, NgForm, NgModel } from '@angular/forms';

@Component({
  ...
  viewProviders: [ { provide: ControlContainer, useExisting: NgForm } ]
})
export class ChildComponent {}

See also

  • Angular2 nested template driven form

Previous version:

I would say it's possible. For example you could add the following code to your

child.component.ts

import { NgForm, NgModel } from '@angular/forms';

@Component({
  selector: 'child-component',
  template: `
      <input type="text" name="thirdControl" [(ngModel)]="thirdControl" />
      <input type="text" name="fourthControl" [(ngModel)]="fourthControl" />
    `
})
export class ChildComponent {
  @ViewChildren(NgModel) ngModels: QueryList<NgModel>;

  constructor(@Optional() private ngForm: NgForm) {}

  ngAfterViewInit() {
    if (this.ngForm) {
      this.ngModels.forEach(model => this.ngForm.addControl(model));
    }
  }
}

Plunker Example

Angular DI system gives us the opportunity to get reference to parent NgForm instance because angular dependency resolution algorithm starts with current node and goes up through tree of elements. In my example we can imagine the follwing tree

              @NgModule providers
                    |
                  my-app
                    |
                   form
          /         |       \
   input[text] input[text] child-component

So when we are requiring NgForm token angular will search it in the next order

child-component
     ||
     \/
    form
     ||
     \/
   my-app
     ||
     \/
  @NgModule

On form element NgForm directive is placed so when can get it. Also we can get any token that was declared on NgForm directive within providers array. And this rule applies to any node.

See also Angular 2 - How does ng-bootstrap provide the NgbRadioGroup and NgbButtonLabel to their NgbRadio directive?

Then i just added child NgModel directives manually to NgForm so they should work together.

like image 135
yurzui Avatar answered Sep 28 '22 03:09

yurzui