【问题标题】:How can I bind to a directive input from within another directive?如何绑定到另一个指令中的指令输入?
【发布时间】:2019-09-26 11:07:35
【问题描述】:

我试图通过将几个验证输入压缩成一个指令来稍微简化我的模板过程,我可以将它们放在需要它们的 <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() { }

}

我的问题是它不允许我在“状态”上使用@HostBinding,它是也位于元素上的 nbInput 指令的输入。

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

有没有一种好方法可以让我从我的指令中绑定到该指令的输入?

【问题讨论】:

  • 你是import { FormsModule } from '@angular/forms'; 并添加到@NgModule({ imports: [ FormsModule ], })
  • @SouravDutta 是的

标签: angular angular-directive


【解决方案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);
    }
}

第一个指令接受一个状态输入,并且宿主元素的 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
    }

第二个指令接受一个状态输入并发出一个状态更改输出,主机元素的 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() {}
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-06
    • 1970-01-01
    • 1970-01-01
    • 2013-11-23
    • 1970-01-01
    • 2014-09-28
    • 2016-09-26
    • 1970-01-01
    相关资源
    最近更新 更多