双向绑定的输出部分不适用于自定义指令

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();