双向绑定的输出部分不适用于自定义指令
Output part of two-way binding doesn't work for custom directive
我正在尝试实现一个带有 属性 的指令,它支持像这样的双向绑定:[(appfocused)]="isFocused"
。组件可以将其 isFocused
属性 设置为 true 以聚焦于某个元素,但一旦元素失去焦点,该变量将恢复为 false。
我读过 (here and here) 实现这种绑定的关键是 @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()
行被命中,但它对 属性 绑定到的值没有影响。
Here is a working example (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;
}
}
按下焦点 link 会按预期聚焦在 textarea
上。但是,单击它不会重置 isFocused
变量。再次按下 link 无效 - isFocused
的值已经为真,因此 Angular 未检测到任何更改。
我错过了什么?
如您提到的文章所述,要使双向绑定 shorthand 语法起作用,输出的名称必须与输入的名称相同 加上“更改”后缀.
所以你就快完成了 - 你只需要正确命名 @Output()
:不是“appfocused”,而是“appfocused改为":
@Output('appfocusedChange')
focusedChange: EventEmitter<boolean> = new EventEmitter();
我正在尝试实现一个带有 属性 的指令,它支持像这样的双向绑定:[(appfocused)]="isFocused"
。组件可以将其 isFocused
属性 设置为 true 以聚焦于某个元素,但一旦元素失去焦点,该变量将恢复为 false。
我读过 (here and here) 实现这种绑定的关键是 @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()
行被命中,但它对 属性 绑定到的值没有影响。
Here is a working example (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;
}
}
按下焦点 link 会按预期聚焦在 textarea
上。但是,单击它不会重置 isFocused
变量。再次按下 link 无效 - isFocused
的值已经为真,因此 Angular 未检测到任何更改。
我错过了什么?
如您提到的文章所述,要使双向绑定 shorthand 语法起作用,输出的名称必须与输入的名称相同 加上“更改”后缀.
所以你就快完成了 - 你只需要正确命名 @Output()
:不是“appfocused”,而是“appfocused改为":
@Output('appfocusedChange')
focusedChange: EventEmitter<boolean> = new EventEmitter();