包裹角材料输入的组件不显示错误样式 [英] Component for wrap angular material input does not show error styles

查看:26
本文介绍了包裹角材料输入的组件不显示错误样式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在一个组件中包含一个 matInput 角度材料,以便在我的应用程序的其他地方重用它,因为我需要管理它的内部状态以将输入类型从文本更改为密码,反之亦然.

I want to enclose a matInput of angular material within a component to reuse it in other places of my application because I need to manage its internal state to change the input type from text to password and viceversa.

我通过实现 ControlValueAccessor 设法做到了,但没有显示验证错误的样式.

I managed to do it by implementing ControlValueAccessor but the styles of validation errors are not being displayed.

密码字段组件:

export class PasswordFieldComponent
  implements OnInit, ControlValueAccessor {

  @ViewChild(DefaultValueAccessor) private valueAccessor: DefaultValueAccessor;

  @Input() customClass: string;
  @Input() customPlaceholder: string;
  @Input() required = true;

  hide = true;

  constructor() { }

  ngOnInit() {
  }

  private propagateChange = (_: any) => { };

  private onChange(event) {
    this.propagateChange(event.target.value);
  }

  private onTouch() { }

  registerOnChange(fn: any): void {
    this.valueAccessor.registerOnChange(fn);
  }

  registerOnTouched(fn: any): void {
    this.valueAccessor.registerOnTouched(fn);
  }

  setDisabledState(isDisabled: boolean): void {
    this.valueAccessor.setDisabledState(isDisabled);
  }

  writeValue(value: any): void {
    this.valueAccessor.writeValue(value);
  }

}

密码字段模板:

<mat-form-field class="full-width {{ customClass }}">

  <input
    matInput
    ngDefaultControl
    placeholder="{{ customPlaceholder }}"
    [required]="required"
    [type]="hide ? 'password' : 'text'"
    (input)="onChange($event)">

  <button mat-icon-button matSuffix (click)="hide = !hide" [attr.aria-label]="'Hide password'" [attr.aria-pressed]="hide">
    <mat-icon>{{hide ? 'visibility_off' : 'visibility'}}</mat-icon>
  </button>

</mat-form-field>

推荐答案

我的评论中的代码是最简单的自定义表单控件,里面有一个材料输入".这个想法是创建询问控件本身的自定义 ErrorStateMatcher.因此,当我们的自定义控件无效时,内部材料输入不会显示错误,否则会显示错误

The code from my comments is make the "most simple custom form control that has a material input inside". The idea is create custom ErrorStateMatcher that ask about the control itself. So, out inner material input show errors not when it was invalid else when our custom control was invalid

这个 ErrorStateMatcher 需要知道我们的控件,所以我们将创建一个构造函数来注入这个控件(我在构造函数中注入了另一个对象错误",以使材料输入无效")

This ErrorStateMatcher need the know about our control, so we are going to create a constructor to inject this control (I inject in constructor another object "errors" to alow make "invalid" the material input)

class CustomFieldErrorMatcher implements ErrorStateMatcher {
  constructor(private customControl: FormControl,private errors:any) { }

  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    return this.customControl && this.customControl.touched &&(this.customControl.invalid || this.errors);
  }
}

.html 就像

<mat-form-field>

    <input #input="ngModel" [ngModel]="value" (ngModelChange)="value=$event;onChange($event)"
    matInput
    [errorStateMatcher]="errorMatcher()"
    [placeholder]="placeholder"
    [type]="hide ? 'password' : 'text'"
    (blur)="onTouched()"
    >
    <button mat-icon-button matSuffix (click)="hide = !hide" [attr.aria-label]="'Hide password'" [attr.aria-pressed]="hide">
    <mat-icon>{{hide ? 'visibility_off' : 'visibility'}}</mat-icon>
  </button>
    <mat-error *ngIf="control?.errors?.required">
        Please enter a {{placeholder}}
    </mat-error>
    <mat-error *ngIf="errors?.errorMatch">
        Must match
    </mat-error>

</mat-form-field>

最重要的是这个

[errorStateMatcher]="errorMatcher()"

看到使用 [ngModel] 和 (ngModel), (blur) 标记自定义 formControl touched".我添加了一个 mat-error *ngIf="errors?.errorMatch.这是一个 @Input() ,它获取 Form 的错误值.这是因为我们制作了一个具有自定义的 FormGroup如果password"和repeatpassword"这两个字段不匹配,则会出错.

See that use [ngModel] and (ngModel), (blur) mark the custom formControl "touched". I add a mat-error *ngIf="errors?.errorMatch. This is a @Input() that get the value of error of Form. This is because we are make a FormGroup that has an custom error if the two fields "password" and "repeatpassword" not match.

我们的自定义表单控件就像

Our custom form control is like

export class CustomSelectComponent implements AfterViewInit, ControlValueAccessor {

  control: FormControl
  onChange: any = () => { };
  onTouched: any = () => { };

  value: any;
  @Input() disabled: boolean;
  @Input() placeholder = '';
  @Input() errors:any=null;

  errorMatcher() {
    return new CustomFieldErrorMatcher(this.control,this.errors)
  }
  constructor(public injector: Injector) {
  }

  ngAfterViewInit(): void {
    const ngControl: NgControl = this.injector.get(NgControl, null);
    if (ngControl) {
      setTimeout(() => {
        this.control = ngControl.control as FormControl;
      })
    }
  }

查看如何在 ngAfterViewInit 中获取 ngControl,errorMatcher() 如何返回一个新的 CustomFieldErrorMatcher 以及如何传递control"和errors"的值.

See how get the ngControl in the ngAfterViewInit, how errorMatcher() return a new CustomFieldErrorMatcher and how pass the values of "control" and "errors".

我们的 app.component 就像

Well our app.component is like

  ngOnInit() {
    this.myForm = new FormGroup(
      {
        password: new FormControl("", Validators.required),
        repeatpassword: new FormControl("", Validators.required)
      },
      this.matchControls("password", "repeatpassword")
    );
  }

  matchControls(field1, field2) {
    return (group: FormGroup) => {
      const control1 = group.get(field1);
      const control2 = group.get(field2);
      return control1 && control2 &&
        control1.value && control2.value &&
        control1.value != control2.value
        ? { errorMatch: "must match" }: null;
    };
  }

app.component 的 .html 是

The .html of the app.component is

<form [formGroup]="myForm" autocomplete="off">
    <app-custom-input placeholder="Password" formControlName="password" >
    </app-custom-input>
    <app-custom-input placeholder="Repeat password" formControlName="repeatpassword" [errors]="myForm.errors?.errorMatch?myForm.errors:null" >
    </app-custom-input>
</form>

stackblitz

在自定义组件上添加了这个监听器.你也可以做'blur'事件.

added this listener on the custom component. You can also do it 'blur' event.

https://stackoverflow.com/a/59086644/12425844

@HostListener('focusout', ['$event.target'])
  onFocusout() {
    this.onTouched();
  }
And also calling onTouched when setting any value.

 writeValue(value: any) {
    this.onTouched();
    this.Value = value ? value : '';
}

这篇关于包裹角材料输入的组件不显示错误样式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆