角材料<mat-error>未显示在自定义组件中

时间:2019-04-20 17:43:18

标签: angular angular-material

所以我一直在做很多研究,但是我无法弄清楚。

我想使用Angular材质表单控件制作Textbox组件

tutorial之后,我实现了以下步骤

textbox.component.html

<mat-form-field>
    <input matInput type="text" [placeholder]="placeholder" [(ngModel)]="value" />
    <mat-error>This field is required</mat-error>
</mat-form-field>

textbox.component.ts

import { Component, Input, forwardRef, OnDestroy, ElementRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor, FormControl, NgControl } from '@angular/forms';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
import { MatFormFieldControl } from '@angular/material';
import { Subject } from 'rxjs';
import { FocusMonitor } from '@angular/cdk/a11y';

@Component({
    selector: 'text-box',
    templateUrl: './text-box.component.html',
    styleUrls: ['./text-box.component.scss'],
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => TextBoxComponent),
            multi: true
        },
        {
            provide: MatFormFieldControl,
            useExisting: TextBoxComponent
        }
    ]
})
export class TextBoxComponent implements ControlValueAccessor, MatFormFieldControl<any>, OnDestroy {
    static nextId = 0;

    stateChanges: Subject<void> = new Subject<void>();
    id: string = `text-box-${TextBoxComponent.nextId++}`;
    ngControl: NgControl = null;
    focused: boolean = false;
    empty: boolean;
    shouldLabelFloat: boolean;
    disabled: boolean = false;
    errorState: boolean = false;
    controlType?: string = 'text-box';
    autofilled?: boolean;
    describedBy: string = '';

    @Input()
    get placeholder(): string {
        return this._placeholder;
    }
    set placeholder(value: string) {
        this._placeholder = value;
        this.stateChanges.next();
    }
    private _placeholder: string;

    @Input()
    get required(): boolean {
        return this._required;
    }
    set required(value: boolean) {
        this._required = coerceBooleanProperty(value);
        this.stateChanges.next();
    }
    private _required = false;

    @Input() name: string;

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

    isDisabled: boolean = false;

    @Input('value') val: string;
    get value(): any {
        return this.val;
    }
    set value(val: any) {
        this.val = val;
        this.errorState = !val;
        this.onChange(val);
        this.onTouched();
        this.stateChanges.next();
    }

    constructor(private fm: FocusMonitor, private elRef: ElementRef<HTMLElement>) {
        fm.monitor(elRef, true).subscribe(origin => {
            this.focused = !!origin;
            this.stateChanges.next();
        });
    }

    writeValue(value: any): void {
        if (value) {
            this.value = value;
        }
    }
    registerOnChange(fn: any): void {
        this.onChange = fn;
    }
    registerOnTouched(fn: any): void {
        this.onTouched = fn;
    }
    setDisabledState?(isDisabled: boolean): void {
        this.isDisabled = isDisabled;
    }

    setDescribedByIds(ids: string[]): void {
        this.describedBy = ids.join(' ');
    }
    onContainerClick(event: MouseEvent): void {
        if ((event.target as Element).tagName.toLowerCase() != 'input') {
            this.elRef.nativeElement.querySelector('input')!.focus();
        }
    }

    ngOnDestroy(): void {
        this.stateChanges.complete();
        this.fm.stopMonitoring(this.elRef);
    }
}

并基本上以这种形式使用它:

<form [formGroup]="someForm" (ngSubmit)="onSubmit()">
    <acs-text-box formControlName="username" [placeholder]="'Form control'"> </acs-text-box>
    <my-button [type]="'submit'">Submit</my-button>
</form>

这是我的问题,我正在尝试在textbox.component.html模板中进行渲染,但它不起作用

我尝试了多种操作,例如在textbox.component.ts中设置errorState = true,但是什么也没有发生。

我已经尝试过了

<mat-form-field>
    <acs-text-box formControlName="username" [placeholder]="'Form control'"> </acs-text-box>
    <mat-error>This field is required</mat-error>
</mat-form-field>

通过设置errorState = true可以正常工作,但是当我将mat-error带回到文本框组件模板内部时,它将无法工作。

是否可以在文本框组件模板中进行渲染?还是仅用角形材料是不可行的,我将以自己的方式实施?

提前谢谢!

1 个答案:

答案 0 :(得分:1)

尝试这样做:

<mat-form-field>
    <input matInput type="text" [placeholder]="placeholder" [(ngModel)]="value" required #inputValue="ngModel" />
    <mat-error *ngIf="(inputValue.touched && inputValue.invalid)">This field is required</mat-error>
</mat-form-field>