如何绑定到另一个指令中的指令输入?

How can I bind to a directive input from within another directive?

我试图通过将几个验证输入压缩到一个指令中来稍微简化我的模板化过程,我可以将它们放在需要它们的 <input> 元素上。

有问题的输入如下所示:

<input [(ngModel)]='options.org_name' required id="org_name" type="text" nbInput fullWidth
                placeholder="What is your organization called?"
                [appValidating]='this'
                minlength="3" maxlength="40" />

我的指令是 [appValidating]。 appValidating 的代码是这样的:

@Directive({
  selector: '[appValidating]'
})
export class ValidatingDirective {

  @Input('appValidating') validator: IValidatingComponent;
  @Input() id: string;

  @HostBinding('status')
  get status() {
    return this.validator.validity[this.id] === true ? null : 'danger';
  }

  @HostListener('input', ['$event'])
  onInput(event: any) {
    this.validator.checkValidity(this.id, event);
  }

  constructor() { }

}

我的问题是它不允许我在 'status' 上使用 @HostBinding,这是 nbInput 指令的输入,它也位于元素上。

Uncaught (in promise): Error: Template parse errors: Can't bind to 'status' since it isn't a known property of 'input'.

有什么好的方法可以让我在我的指令中绑定到该指令的输入吗?

首先,您可以使用 HostBinding 设置属性,但最终无法满足您的需要

@HostBinding('attr.status') // this will set an attribute on the element

这对您不起作用的原因是它不是您正在设置的 angular 感知属性,因此它无法绑定到 nbInput 指令的 @Input。

我想了想这个问题,并尝试了几种解决问题的方法,最后选择了这个,但诚然,要让它起作用,您可能需要具有更改这两个指令的访问权限和能力。

第一个指令

@Directive({
    selector: '[firstDirective]',
})
export class FirstDirective {
    @Input('status') private status: boolean;

    @HostListener('click', ['$event'])
    public onHostClicked(event: MouseEvent): void {
        event.preventDefault();
        event.stopImmediatePropagation();
        event.stopPropagation();
        console.log('first directive: ', this.status);
    }
}

第一个指令接受一个状态输入和主机元素的 onClick 记录状态是什么

第二个指令

@Directive({
    selector: '[secondDirective]',
})
export class SecondDirective {
    @Input('status') private status = false;
    @Output('statusChange') private statusChangeEvent = new EventEmitter(
        this.status,
    ); // an output event named as attributeNameChange is how you tell a two way bound attribute that it's value has changed

    @HostListener('click', ['$event'])
    public onHostClicked(event: MouseEvent): void {
        event.preventDefault();
        event.stopImmediatePropagation();
        event.stopPropagation();

        this.status = !this.status; // toggle the boolean
        this.statusChangeEvent.emit(this.status); // emit that it changed
    }

第二个指令接受状态输入并发出 statusChange 输出,宿主元素的 onClick 翻转状态值并发出它已更改。

组件

@Component({
    template: '<button firstDirective secondDirective [(status)]="status">Change Status</button>',
})
export class Component {
    status = true; // the value in the implementing component that is being toggled
    constructor() {}
}

所以在上面的示例中,正在发生的事情是在两个指令都可以访问的实现组件中设置了一个值,它充当它们两者之间的传递。每当第二个指令看到点击时,它会翻转状态布尔值,第一个指令会看到该变化。