Angular класс реализует MatFormFieldControl и ControlValueAccessor, но по-прежнему выдает ошибку «поле mat-form должно содержать MatFormFieldControl» - PullRequest
0 голосов
/ 12 июля 2020

Я пытаюсь создать оболочку для компонента флажка из материала angular, но получаю сообщение об ошибке «поле формы-мат должно содержать MatFormFieldControl», хотя класс реализует интерфейс MatFormFieldControl. Идея состоит в том, чтобы показать ошибки для компонента custom-checkbox в самом компоненте, а также иметь возможность передавать настраиваемые сообщения об ошибках от родителя. Пожалуйста, помогите мне в этом. Спасибо!

custom-checkbox.component.ts

import { Component, OnInit, Input, Self, Optional, Output, EventEmitter, HostBinding, Injector, DoCheck, ElementRef, ViewChild } from '@angular/core';
import { ControlValueAccessor, FormControl, NgControl, ValidatorFn, Validators } from '@angular/forms';
import { MatFormFieldControl } from '@angular/material/form-field';
import { Subject } from 'rxjs';
import { coerceBooleanProperty } from '@angular/cdk/coercion';

@Component({
  host: {
    '[id]': 'id',
    '[attr.aria-describedby]': 'describedby'
  },
  selector: 'custom-checkbox',
  templateUrl: './custom-checkbox.component.html',
  styleUrls: ['./custom-checkbox.component.scss'],
  providers: [
    { provide: MatFormFieldControl, useExisting: CustomCheckboxComponent }
  ]
})
export class CustomCheckboxComponent implements OnInit, DoCheck, ControlValueAccessor, MatFormFieldControl<boolean> {

  public _required: boolean = false;
  private _disabled: boolean = false;
  private _checked: boolean = false;

  customFormControl: FormControl;
  validators: ValidatorFn | ValidatorFn[];
  name: string = "checkbox-name";
  static nextId = 0;

  // from implementing MatFormFieldControl
  stateChanges: Subject<void> = new Subject<void>();
  placeholder: string;
  ngControl: NgControl;
  focused: boolean = false;
  shouldLabelFloat: boolean;
  errorState: boolean = false;
  controlType?: string = "customCheckbox";
  autofilled?: boolean;

  @Input() checkboxData: any;

  @Input() get required() { return this._required; }
  set required(req) {
    this._required = coerceBooleanProperty(req);
    this.stateChanges.next();
  }

  @Input() get value(): boolean {
    return this._checked;
  }
  set value(value) {
    this._checked = coerceBooleanProperty(value);
    this.customFormControl.setValue(this._checked);
    this.propagateChange(value);
    this.stateChanges.next();
  }

  get empty() {
    if (this.customFormControl.pristine || this.customFormControl.untouched) return true;
    else return false;
  }

  @Input() get disabled(): boolean { return this._disabled; }
  set disabled(value) {
    this._disabled = coerceBooleanProperty(value);
    this._disabled ? this.customFormControl.disable() : this.customFormControl.enable();
    this.stateChanges.next();
  }

  @Output() checkboxEvent: EventEmitter<any>;

  @HostBinding('attr.aria-describedby') describedBy = '';

  @HostBinding() id = `custom-checkbox-component-${CustomCheckboxComponent.nextId++}`;

  constructor(@Optional() @Self() public controlDir: NgControl, public injector: Injector) {
    this.customFormControl = new FormControl();
    this.checkboxEvent = new EventEmitter();
    if (this.controlDir != null) {
      this.controlDir.valueAccessor = this;
    }
  }

  ngOnInit(): void {
    this.ngControl = this.injector.get(NgControl);
    if (this.ngControl != null) this.ngControl.valueAccessor = this;

    this.validators = this.required ? Validators.required : this.validators;
    this.customFormControl.setValidators(this.validators);
    this.customFormControl.updateValueAndValidity();
  }

  ngDoCheck() {
    if (this.ngControl) {
      this.errorState = this.ngControl.invalid && (this.ngControl.touched || this.ngControl.dirty);
      this.stateChanges.next();
    }
  }

  setDescribedByIds(ids: string[]): void {
    this.describedBy = ids.join(' ');
  }

  onContainerClick(event: MouseEvent): void {
    // throw new Error("Method not implemented.");
  }

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

  writeValue(value: any): void {
    if (value != undefined) this.customFormControl.setValue(value);
  }

  registerOnChange(fn: (_: any) => {}): void {
    this.propagateChange = fn;
  }

  registerOnTouched(fn: () => {}): void {
    this.onTouched = fn;
  }

  setDisabledState(isDisabled: boolean): void {
    // this.disabled = isDisabled;
  }

  selectionChanged(event: any) {
    console.info("Checkbox %s : ", event.checked, event.source.value);
    this.stateChanges.next()
    this.checkboxEvent.emit(event.checked);
  }

  ngOnDestroy() {
    this.stateChanges.complete();
  }

}

custom-checkbox.component. html

<mat-form-field>
  <mat-checkbox #checkbox [formControl]="customFormControl" [name]="name" [required]="this.required" [value]="this.checkboxData"
    [checked]="value" (change)="selectionChanged($event);propagateChange($event.checked)">
    {{checkboxData?.value}}</mat-checkbox>&nbsp;&nbsp;

  <mat-error *ngIf="customFormControl.invalid && (customFormControl.dirty || customFormControl.touched)">
    Error Message
  </mat-error>
</mat-form-field>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...