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

时间:2019-05-08 16:43:32

标签: angular angular-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'.

我是否可以从我的指令中绑定该指令的输入?

1 个答案:

答案 0 :(得分:1)

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

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

这对您不起作用的原因是,它不是您要设置的角度感知属性,因此它无法绑定到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);
    }
}

第一个指令的状态为Input,主机元素的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() {}
}

因此,在上面的示例中,正在发生的事情是在实现组件中设置了一个值,两个指令都可以访问该值,并且该值充当两个指令之间的传递。每当第二条指令单击时,它就会翻转状态布尔值,而第一条指令会看到更改。