子组件的Angular Form验证

Gui*_*ele 1 forms typescript angular-components angular

我写了一个动态表单,其中有一个主要部分和子部分基于在主要部分(widget.type)中选择的类型.使用ngSwitch显示和隐藏子部件.

表单的HTML如下所示:

<form class="widget-form cc-form" (ngSubmit)="saveChanges()" novalidate>
  <div class="forms-group">
    <label for="title" i18n="@@title">Titel</label>
    <input class="form-control" id="title" name="title" type="text" [(ngModel)]="widget.title" required />
  </div>

  <div class="forms-group">
    <label class="checkbox-label" for="show" i18n>
      <input id="show" name="show" type="checkbox" [(ngModel)]="widget.show" /> <span>Titel tonen in app</span>
    </label>
  </div>

  <div class="forms-group">
    <label for="type" i18n="@@type">Type</label>
    <select class="form-control" id="type" name="type" [(ngModel)]="widget.type" required>
      <option value="text-widget" i18n="@@Text">Tekst</option>
      <option value="tasklist-widget" i18n="@@Tasklists">Takenlijst</option>      
      <option value="image-widget" i18n="@@Text">Afbeelding(en)</option>
      <option value="video-widget" i18n="@@Video">Youtube</option>
      <option value="link-widget" i18n="@@Link">Link</option>
      <option value="contacts-widget" i18n="@@Contacts">Contactpersonen</option>
      <option value="attachment-widget" i18n="@@Attachments">Bijlage(n)</option>
    </select>
  </div>

  <ng-container [ngSwitch]="widget.type">

    <text-widget *ngSwitchCase="'text-widget'" [data]="widget"></text-widget>

    <tasklist-widget *ngSwitchCase="'tasklist-widget'" [data]="widget"></tasklist-widget>

    <image-widget *ngSwitchCase="'image-widget'" [data]="widget"></image-widget>

    <video-widget *ngSwitchCase="'video-widget'" [data]="widget"></video-widget>

    <link-widget *ngSwitchCase="'link-widget'" [data]="widget"></link-widget>

    <contacts-widget *ngSwitchCase="'contacts-widget'" [data]="widget"></contacts-widget>

    <attachment-widget *ngSwitchCase="'attachment-widget'" [data]="widget"></attachment-widget>

  </ng-container>

</form>
Run Code Online (Sandbox Code Playgroud)

每个小部件都是它自己的组件.

问题是表单验证仅检查主要部分的输入并忽略子部分(窗口小部件组件).如何确保小部件的输入字段包含在验证中?

我尝试将一个isValid()方法添加到窗口小部件组件,但我无法获取组件的实例,可能是因为它们在ngSwitch中使用.@ContentChild,@ ContentChildren,@ ViewChild等都返回undefined.

小智 23

对于未来的谷歌员工,

我有一个与此类似的问题,尽管子组件较少,并且在深入研究了@penleychan 的上述主题之后,我发现了一个小宝石,它为我解决了这个问题,而无需实现自定义指令。

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

@Component({
    ....
    viewProviders: [{ provide: ControlContainer, useExisting: NgForm }],
})
Run Code Online (Sandbox Code Playgroud)

这适用于我的嵌套表单。只需要添加到组件中,哪些直接包含输入

https://github.com/angular/angular/issues/9600#issuecomment-522898551

  • 这对我有用 - 我花了很多时间研究这个,所以谢谢。子组件未由父表单进行验证 - 在我的场景中,为 ControlContainer 提供现有的 NgForm 实例就足以将验证从子组件传递到父组件。 (2认同)
  • 请注意,您应该将上面的“viewProviders”代码行添加到子组件,而不是父组件 (2认同)

pen*_*han 8

希望我不会太晚.我最近在模板方法上偶然发现了这个问题,因为反应形式不适合我需要做的事情......

该问题与ControlValueAccessor您的组件需要实现的问题有关.但是我无法做到这一点.

请参阅:https://github.com/angular/angular/issues/9600

由andreev-artem提供的解决方案运行良好,我还添加了我的解决方案,将其包装在内部ngModelGroup而不是在form根对象controls属性中.

对于你没有使用的情况,ngModelGroup你可以拥有这个指令

@Directive({
selector: '[provide-parent-form]',
providers: [
    {
        provide: ControlContainer,
        useFactory: function (form: NgForm) {
            return form;
        },
        deps: [NgForm]
    }
  ]
})
export class ProvideParentForm {}
Run Code Online (Sandbox Code Playgroud)

用法:在[(ngModel)]添加指令之前,在根元素的组件中.例:

<div provide-parent-form> 
   <input name="myInput" [(ngModel)]="myInput"> 
</div>
Run Code Online (Sandbox Code Playgroud)

现在,如果您form object在控制台中输出您的内容,或者您可以在controlsform的对象属性下看到组件的控件.