动态创建一个 <mat-error> 组件并将其正确投影到父 <mat-form-field> 组件中

mtp*_*ltz 3 angular-material angular angular-reactive-forms

使用ComponentFactoryResolver动态创建组件很简单,但是当我尝试<mat-error><mat-form-field>. 我一直在使用 Netanel Basal 的示例和 Bootstrap 组件,它非常适合生成表单控制错误,但由于 Angular Material 中使用的内容投影,<mat-error>我似乎无法让它适用于 Angular Material v8.2.1。

是否可以<mat-error>在 a 中动态创建a<mat-form-field>并使其内容项目正确?

joh*_*667 9

我之前已经试过这- MatFormField拿起MatError通过s ContentChildren。由于它是内容投影,因此动态添加或删除元素MatError不起作用 - 内容模板的编译和处理方式与其他模板不同。

您在评论中提到您正在尝试跨模板处理一致的错误消息……为什么不将 a 添加directive <mat-error>基于父控件的表单验证状态控制错误消息的元素?

但是,如果您要控制模板,则不能使用指令。你可以,但是,创建一个组件,使用它像一个指令:

@Component({
  selector: '[matErrorMessages]',
  template: '{{ error }}'
})
export class MatErrorMessagesDirective implements AfterViewInit {
  
  public error = '';
  private inputRef: MatFormFieldControl<MatInput>;

  constructor(private _inj: Injector) { }

  public ngAfterViewInit() {
    // grab reference to MatFormField directive, where form control is accessible.
    let container = this._inj.get(MatFormField);
    this.inputRef = container._control;

    // sub to the control's status stream
    this.inputRef.ngControl.statusChanges.subscribe(this.updateErrors);
  }


  private updateErrors = (state: 'VALID' | 'INVALID') => {
    if (state === 'INVALID') {
      // active errors on the FormControl
      let controlErrors = this.inputRef.ngControl.errors;

      // just grab one error
      const firstError = Object.keys(controlErrors)[0];
      
      if(firstError === 'required')
        this.error = 'This field is required.';
 
      if(firstError === 'minlength')
        this.error = 'This field should be longer.';

      if(firstError === 'error from my own custom validator')
        this.error = 'You get the point.';
      // ..... 
    }
  }
Run Code Online (Sandbox Code Playgroud)

然后在模板中....

<mat-error matErrorMessages></mat-error>
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以按照预期的方式MatFormField控制 的存在MatError,但您可以以一种本地化的、干净的方式控制错误元素的内容

以上的stackblitz:https ://stackblitz.com/edit/angular-sjkfft

您必须深入了解 Material 组件的私有成员,这是有问题的做法,并且可能会因库更新而中断,但它可以工作。

我实际上有一个针对这种类型的错误消息的存储库,它是为@angular/material 的旧版本编写的,但我也能够掌握Validator它本身以获得更好的错误消息,并且正在注入整个自定义列表该验证器的验证器/错误进入模块:https : //github.com/joh04667/material-error-messages