【问题标题】:Angular 6 - can't inject NgControl in validator directiveAngular 6 - 无法在验证器指令中注入 NgControl
【发布时间】:2019-10-30 22:09:59
【问题描述】:

我在创建要在模板驱动表单中使用的自定义验证器时遇到问题。我想构造函数注入宿主元素的 NgControl,它也有一个 NgModel 指令。但我不断收到以下 Angular 编译错误:

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 的提供者。

我似乎无法在模板驱动表单的上下文中找到更多关于此的信息,因此我非常感谢有关如何解决此问题的任何想法。

提前致谢, 约书亚

【问题讨论】:

  • 对了,用 [(ngModel)]="SomeProperty" 代替 ngModel 的应用也没有用...

标签: angular typescript angular-directive


【解决方案1】:

没有找到解决方案,但确实找到了解决方法:通过注射器。

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

编辑

只需从指令本身中删除提供程序,然后在模块中提供它。

Stackblitz

【讨论】:

  • (如果不起作用,请考虑在您的组件中声明一个ngControl 变量,并在您的构造函数代码中设置它)
  • 我对这种方法的问题也是 Angular 抱怨这样的调用 this.injector.get(NgControl) 已被弃用。当我这样做时,我也只是返回 null ...
  • 从未见过折旧警告,但至于第二个问题,这意味着您的指令中没有 NgControl 实例。这可能是因为您使用@Self 覆盖了注入器,请尝试将其删除:here is more information
  • 删除包括@Self()在内的所有注释似乎没有任何区别
  • @JoshuaSchroijen 已经在原始答案下的编辑中添加了它。我保留第一个,因为它已经救了我好几次了 :) 完全同意你的看法,但是I don't think the frameworks are the only ones behaving strangely ...
猜你喜欢
  • 2017-02-10
  • 1970-01-01
  • 2020-07-15
  • 2016-09-11
  • 2016-06-23
  • 1970-01-01
  • 1970-01-01
  • 2020-05-24
  • 1970-01-01
相关资源
最近更新 更多