Angular V11: NullInjectorError: No provider for ControlContainer

Angular V11: NullInjectorError: No provider for ControlContainer

我根据这篇文章进行了自定义输入:medium.com: dont-reinvent-the-wheel

这是我的代码,是严格模式▼

// input.component.ts

import { Component, Input, ViewChild } from '@angular/core';
import {
    ControlContainer,
    ControlValueAccessor,
    FormControl,
    FormControlDirective,
    NG_VALUE_ACCESSOR
} from '@angular/forms';
import {
    FloatLabelType,
    MatFormFieldAppearance
} from '@angular/material/form-field';

@Component({
    selector: 'app-input',
    templateUrl: './input.component.html',
    styleUrls: ['./input.component.scss'],
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: InputComponent,
            multi: true
        }
    ]
})
export class InputComponent implements ControlValueAccessor {
    isDisabled!: boolean;

    @Input() isRequired!: boolean;

    @Input() label!: string;

    @Input() placeholder!: string;

    @Input() readonly!: boolean;

    @Input() appearance: MatFormFieldAppearance = 'fill';

    @Input() floatLabel: FloatLabelType = 'auto';

    @ViewChild(FormControlDirective, { static: true })
    formControlDirective!: FormControlDirective;

    @Input() formControl!: FormControl;

    @Input() formControlName!: string;

    get control(): FormControl {
        return (
            this.formControl ||
            this.controlContainer.control?.get(this.formControlName)
        );
    }

    constructor(private controlContainer: ControlContainer) {}

    clearInput(): void {
        this.control.setValue('');
    }

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

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

    writeValue(obj: any): void {
        this.formControlDirective.valueAccessor?.writeValue(obj);
    }

    setDisabledState(disabled: boolean): void {
        this.isDisabled = disabled;
    }
}
<!-- input.component.html -->

<div class="custom-input">
    <mat-form-field
        [appearance]="appearance"
        [floatLabel]="floatLabel"
        class="custom-input__form-field"
    >
        <mat-label class="custom-input__label"
            >{{ label }} <span *ngIf="isRequired && label">*</span></mat-label
        >
        <input
            class="custom-input__value"
            matInput
            type="text"
            [formControl]="$any(control)"
            [placeholder]="placeholder"
            [readonly]="readonly"
        />
        <button
            class="custom-input__clear-btn"
            matSuffix
            mat-icon-button
            aria-label="Clear"
            *ngIf="$any(control).value && !readonly"
            (click)="clearInput()"
        >
            <mat-icon>close</mat-icon>
        </button>
    </mat-form-field>
</div>

没有编译错误但是浏览器记录了这个错误▼

ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(ClientsListModule)[ControlContainer -> 
ControlContainer -> ControlContainer -> ControlContainer -> ControlContainer -> ControlContainer]: 
  NullInjectorError: No provider for ControlContainer!
NullInjectorError: R3InjectorError(ClientsListModule)[ControlContainer -> ControlContainer -> ControlContainer -> 
ControlContainer -> ControlContainer -> ControlContainer]: 
  NullInjectorError: No provider for ControlContainer!

我在这里检查了类似的问题 and here No provider for ControlContainer,根据他们的说法,问题在于没有同时导入 ReactiveFormsModuleFormsModule在各自的模块中,但我正在导入它们,但我仍然看到该错误。

更新 1: 在组件中<app-input>的使用方式如下▼

因为在某些情况下您似乎使用了 formControl 而没有 formGroup,所以在这些情况下使用 @Optional 装饰器使 controlContainer 为 null。

constructor(@Optional() private controlContainer: ControlContainer) {}