【问题标题】:Form in form. Can there be inheritance of form controls?形式中的形式。表单控件可以继承吗?
【发布时间】:2018-03-01 14:46:34
【问题描述】:

我有两个组件:ParentComponent 和 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" />

现在,{{form.value | json}} 返回{ "firstControl": "", "secondControl": "" },很明显。我的问题是:有没有办法从子组件中继承表单控件?为 ParentComponent 获取 { "firstControl": "", "secondControl": "", "thirdControl": "", "fourthControl": "" } 的正确方法是什么?可能吗?

【问题讨论】:

    标签: forms angular typescript angular-forms


    【解决方案1】:

    更新:

    确实有更简单的方法:

    import { FormsModule, ControlContainer, NgForm, NgModel } from '@angular/forms';
    
    @Component({
      ...
      viewProviders: [ { provide: ControlContainer, useExisting: NgForm } ]
    })
    export class ChildComponent {}
    

    另见

    以前的版本:

    我会说这是可能的。例如,您可以将以下代码添加到您的

    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 系统让我们有机会获得对父 NgForm 实例的引用,因为角度依赖解析算法从当前节点开始,并向上遍历元素树。在我的例子中,我们可以想象下面的树

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

    所以当我们需要 NgForm 令牌时,Angular 会按下一个顺序搜索它

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

    在表单元素上放置NgForm 指令,以便何时可以获取它。我们还可以获取在providers 数组中的NgForm 指令上声明的任何令牌。而且这条规则适用于任何节点。

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

    然后我只是手动将子 NgModel 指令添加到 NgForm 以便它们应该一起工作。

    【讨论】:

    • 多么棒的帖子!
    • 完美的解释。非常感谢,伙计。
    • 你也可以展示一个测试吗?真的在考试中挣扎
    • 如何在 HTML 中访问 NgForm(使用更简单的方法)?
    【解决方案2】:

    Angular 有两种形式,模板驱动和响应式。模板驱动表单无法实现您想要做的事情,您需要查看Reactive Forms

    一般来说,它通过在组件中创建一个表单对象并在模板中使用它来工作。 Angular 说这实际上更灵活,更容易测试,但我认为语法更难理解。

    您会希望在您的父组件中使用它:

      myForm: FormGroup; 
    
      constructor(private fb: FormBuilder) { // <--- inject FormBuilder
        this.createForm();
      }
    
      createForm() {
        this.myForm = this.fb.group({
          firstControl: '',
          secondControl: '',
          thirdControl: '',
          fourthControl: ''
        });
      }
    

    你的父模板看起来像这样:

    <form [formGroup]="myForm" novalidate>
    <input type="text"formControlName="firstControl" />
         <input type="text" formControlName="secondControl" />
         <child-component [parentFormGroup]="myForm">
    </form>
    

    您的孩子将接受表单组作为输入,模板将如下所示:

    <div class="form-group" [formGroup]="parentFormGroup">
      <input type="text" formControlName="thirdControl" />
      <input type="text" formControlName="fourthControl" />
    </div>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-06
      • 1970-01-01
      • 1970-01-01
      • 2014-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-12
      相关资源
      最近更新 更多