angular - 如何绑定(bind)到另一个指令中的指令输入?

标签 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,“status”是也位于元素上的 nbInput 指令的输入。

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

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

最佳答案

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

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

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

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

关于angular - 如何绑定(bind)到另一个指令中的指令输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56045421/

相关文章:

javascript - Angular 8 - 如何通过类名获取最接近的父级?

javascript - 如何在 Angular 2+ 中从父组件更改子组件的 HTML/CSS?

jquery - 如何使用自定义元素单击事件更新范围值?

javascript - AngularJS 指令中具有相同 ng-model 的多个输入元素

angular - 如何使用 Angular Flex Layout 添加边距?

javascript - 功能并不从形式中获取值(value)

java - POST 方法在 Angular2 中不起作用

javascript - 无法访问 Azure Web App Linux 或 Windows 上的 NodeJS 站点

javascript - Angular 计时器指令不适用于 ionic 框架

angular - 为什么我需要调用 detectChanges/whenStable 两次?