Angular 6 - не может внедрить NgControl в директиве валидатора - PullRequest
0 голосов
/ 17 июня 2019

У меня проблема с созданием пользовательского валидатора для использования в форме на основе шаблона.Я хочу, чтобы конструктор внедрил NgControl элемента хоста, который также имеет директиву NgModel.Но я продолжаю получать следующую угловую ошибку компиляции:

ERROR in : Cannot instantiate cyclic dependency! NgModel ("
        <div>
                <label for="name">Your name</label>
                [ERROR ->]<input id="name" type="text" name="name" #name="ngModel" ngModel [requiredIfCondition]="toggleBool" r")

Мой класс директивы выглядит так:

import { Directive, forwardRef, Injector, Input, Self } from '@angular/core';
import { AbstractControl, NG_VALIDATORS, NgControl, Validator } from '@angular/forms';

@Directive({
    selector: '[requiredIf][ngModel]',
    providers: [
        { provide: NG_VALIDATORS, useExisting: forwardRef(() => RequiredIfDirective), multi: true },
    ],
})
export class RequiredIfDirective implements Validator {
    private innerRequiredIfCondition: boolean = false;
    @Input()
    public set requiredIfCondition(val: boolean) {
        this.innerRequiredIfCondition = val;
        let hostControl: AbstractControl | null = this.ngControl.control;
        if (hostControl !== null) {
            hostControl.updateValueAndValidity();
        }
    }

    public constructor(@Self() private readonly ngControl: NgControl) {
    }

    public validate(c: AbstractControl): {[error: string]: string} | null {
        if (this.innerRequiredIfCondition && (c.value === null || c.value === '')) {
            return {
                requiredIf: 'In this context this field is required.',
            };
        }
        return null;
    }
}

Я применяю директиву так:

<div>
    <label for="name">Your name</label>
    <input id="name" type="text" name="name" #name="ngModel" ngModel [requiredIfCondition]="toggleBool" requiredIf />
    <div *ngIf="name.errors && name.errors.requiredIf" class="red-text text-darken-3">
        Name is required now.
    </div>
</div>

Я бы попробовал ввести NgControl вручную, но, поскольку это абстрактный класс, я думаю, что вы больше не можете этого делать.

Я также попытался внедрить AbstractControl вместо NgControl, но система не может найтипровайдер AbstractControl.

Я не могу найти больше информации об этом в контексте шаблонно-управляемых форм, поэтому я был бы очень признателен за любые идеи относительно решения этой проблемы.

Заранее спасибо, Джошуа

1 Ответ

2 голосов
/ 17 июня 2019

Не нашел решения для этого, но нашел обходной путь: через инжектор.

public constructor(
  private injector: Injector
  @Self() private readonly ngControl: NgControl = this.injector.get(NgControl),
) {}

РЕДАКТИРОВАТЬ

Просто удалите провайдера из самой директивы и вместо этого укажите его в модуле.

Stackblitz

...