0

我有一个 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. 然后我将输入值编辑为“Test”,并将值作为“TEST”传播回模型,如预期的那样。
  3. 当我第二次单击“重置”按钮时,ngModel 按预期设置为“重置”,但文本<input>保留为“测试”。我希望它会像第 1 点一样更改为“重置”。

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

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

4

1 回答 1

0

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

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

  @HostListener('change', ['$event']) onChange(event: Event) {
    if (event.target instanceof HTMLInputElement) {
      this.lowerValue = event.target.value?.toLocaleUpperCase();
    }
    this._onChangeCallback(this.lowerValue);
  }
于 2021-11-08T14:18:26.717 回答