HostBinding to value 仅在第一次有效

HostBinding to value works only the first time

我有一个执行值格式化的 ControlValueAccessor 指令,但它的 @HostBinding('value') 只在第一次工作。

@Component({
  selector: 'my-app',
  template: `
  Value: {{value}}<br/>
  <input type="text" uppercase [(ngModel)]="value">
  <button type="button" (click)="reset()">Reset</button>
  `,
})
export class AppComponent {
  value = 'Angular ' + VERSION.major;

  reset() {
    this.value = 'Reset';
  }
}

@Directive({
  selector: 'input[uppercase]',
  providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => UpperCaseInputDirective), multi: true }],
})
export class UpperCaseInputDirective implements ControlValueAccessor {

  @HostBinding('value') lowerValue = '';

  ...
}

请在 https://stackblitz.com/edit/angular-ivy-vfahu3?file=src%2Fapp%2Fapp.component.ts

查看完整示例
  1. 当我第一次点击“重置”按钮时,会按预期将 ngModel 设置为“重置”,并将 <input> 的文本设置为“重置”。
  2. 然后我将输入值编辑为“测试”,该值按预期作为“测试”传播回模型。
  3. 当我第二次单击“重置”按钮时,ngModel 按预期设置为“重置”,但 <input> 的文本仍保留为“测试”。我希望它像在第 1 点中那样更改为“重置”。

你能解释一下这种行为吗?有什么线索吗?

旁注: 我知道上面的示例可以通过其他方式实现,但这只是我使用 <input type="datetime-local> 并且指令翻译的情况的简化ISO 格式的输入值。

我意识到由于 Angular 优化,该值未更新 - 如果它认为该值没有改变,它不会将值传播到 DOM。在第 1 点,它将绑定变量更改为值“Reset”,在第 3 点,它“认为”该值仍然是“Reset”,因此它不会更新 DOM.

当我在 onChange 侦听器(第 2 点)中更新绑定变量 this.lowerValue 时,重置按钮在第 3 点起作用:

  @HostListener('change', ['$event']) onChange(event: Event) {
    if (event.target instanceof HTMLInputElement) {
      this.lowerValue = event.target.value?.toLocaleUpperCase();
    }
    this._onChangeCallback(this.lowerValue);
  }