Угловой материал <mat-error> не отображается в пользовательских компонентах - PullRequest
0 голосов
/ 20 апреля 2019

Так что я провел много исследований, но просто не могу понять.

Я хочу создать компонент Textbox, используя элементы формы Angular Material

Следуя этому учебнику , я реализовал его следующим образом

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, но он не работает

Я пробовал несколько вещей, таких как установка errorState = true в textbox.component.ts, но ничего не происходит.

Я пробовал это

<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 обратно в шаблон компонента textbox, он не работает.

Есть ли способ сделать визуализацию внутри шаблона компонента textbox? или это просто невозможно с угловым материалом, и я буду реализовывать его по-своему?

Заранее спасибо !!

1 Ответ

1 голос
/ 06 мая 2019

Попробуйте сделать так:

<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...