angular - 双向绑定的输出部分在自定义指令中不起作用
我正在尝试实现一个指令,该指令具有一个属性,可以支持这样的双向绑定:[(appfocused)]="isFocused"。组件可以将它的isFocused属性设置为true以将焦点放在某个元素上,但一旦元素失去焦点,该变量就会被重置为false。
我已经阅读过(这里和这里)关于实现这种绑定的关键是为 @Input 和 @Output 设置两个同名的属性,但输出属性的名称要加上 Change 后缀。所以这是我目前的实现(使用 TypeScript):
@Directive({
selector: '[appfocused]'
})
export class FocusedDirective implements OnChanges, AfterViewInit {
@Input('appfocused')
focused: boolean;
@Output('appfocused')
focusedChange: EventEmitter<boolean> = new EventEmitter();
constructor(private elementRef: ElementRef, private renderer: Renderer) { }
ngAfterViewInit() {
this.renderer.listen(this.elementRef.nativeElement, 'blur', () => {
this.setFocused(false);
});
}
ngOnChanges() {
if (this.focused) {
setTimeout(() => {
this.elementRef.nativeElement.focus();
}, 0);
}
}
private setFocused(value: boolean) {
this.focused = value;
this.focusedChange.emit(this.focused);
console.log('focused set to ' + value);
}
}
输入属性工作正常,但我无法让输出属性工作。多亏了 console.log 调用,我知道 focusedChange.emit() 这一行被执行了,但它对绑定该属性的值没有任何影响。
这是一个可运行的示例(plunker)。它包括一个虚拟组件,该组件显示并设置isFocused属性的值:
@Component({
selector: 'my-app',
template: `
<div>
<textarea [(appfocused)]="isFocused"></textarea>
</div>
<a (click)="focus()" href="#">Focus</a>
{{isFocused}}
`,
})
export class App {
isFocused = false;
focus() {
this.isFocused = true;
}
}
按下 Focus 链接会按预期将焦点集中到 textarea 上。然而,点击它以外的地方不会重置 isFocused 变量。再次按下该链接没有效果——isFocused 的值已经为 true,因此 Angular 没有检测到任何变化。
我漏掉了什么?
答案#1
正如你提到的文章所述,要让双向绑定的简写语法生效,输出的名称必须与输入相同加上“Change”后缀。
所以你几乎完成了——你只需要正确命名 @Output():不要用“appfocused”,而是用“appfocusedChange”:
@Output('appfocusedChange')
focusedChange: EventEmitter<boolean> = new EventEmitter();
