表单重置后角度保留输入值

Wel*_*elp 6 typescript angular angular-reactive-forms

我有一个包含两个字段的反应式表单。第一个是使用 ControlValueAccessor 的自定义输入,最后一个只是常规的 HTML 输入。

问题是,执行 form.reset() 后,自定义输入的值将被保留,即使其反应形式的值已经为 null。

在此输入图像描述

正如您在图像中看到的,我第一次输入并清除值时,它运行良好。

但是,第二次及以后,输入值仍然保留在自定义输入组件中。同时,无论我单击“清除输入”多少次,正常的 HTML 输入都会被清除并且运行良好。你能帮我吗?我错过放东西了吗?

文件:

  • app.component.ts/html:表单所在的位置
  • custom-input.component.ts/html:自定义输入组件

表格如下:

.ts 文件

import { Component } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
})
export class AppComponent {
  form: FormGroup;

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      firstName: [{ value: '', disabled: false }],
      lastName: [{ value: '', disabled: false }],
    });
  }

  clearInput() {
    this.form.reset();
  }
}
Run Code Online (Sandbox Code Playgroud)

html 文件:

<form [formGroup]="form">
  <app-custom-input formControlName="firstName"></app-custom-input>
  <input formControlName="lastName" placeholder="Last name" />
  <button (click)="clearInput()">Clear Input</button>
</form>

<br />
<pre>{{ form.value | json }}</pre>
Run Code Online (Sandbox Code Playgroud)

这是自定义输入文件:

.ts 文件:

import { Component, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
  selector: 'app-custom-input',
  templateUrl: './custom-input.component.html',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomInputComponent),
      multi: true,
    },
  ],
})
export class CustomInputComponent implements ControlValueAccessor {
  value: string;
  changed: (value: any) => void;
  touched: () => void;
  isDisabled: boolean;

  writeValue(value: string): void {
    this.value = value;
  }

  registerOnChange(fn: any): void {
    this.changed = fn;
  }

  registerOnTouched(fn: any): void {
    this.touched = fn;
  }

  setDisabledState(isDisabled: boolean): void {
    this.isDisabled = isDisabled;
  }

  onChange(event: Event): void {
    const value: string = (<HTMLInputElement>event.target).value;

    this.changed(value);
  }
}
Run Code Online (Sandbox Code Playgroud)

html 文件:

<input
  placeholder="First name"
  [disabled]="isDisabled"
  [value]="value"
  (input)="onChange($event)"
  (blur)="touched()"
/>
Run Code Online (Sandbox Code Playgroud)

完整的工作代码在这里

Ant*_*nko 4

好吧,你做得很好,但是,你必须对这个问题进行更深入的研究。如果您仔细阅读 HTML 规范,您可能会发现html 元素value的属性input只是一个初始值。这就是为什么如果您按下重置按钮(实际上您在那里分配值并writeValue调用方法),您只能得到第一个更改。

因此,解决方案有多种,最简单且与您的代码风格相关的解决方案是获取对输入的引用并手动分配值:

自定义输入.component.html

<input
  placeholder="First name"
  [disabled]="isDisabled"
  (input)="onChange($event)"
  (blur)="touched()"
  #inputRef
/>

Run Code Online (Sandbox Code Playgroud)

自定义输入.component.ts

export class CustomInputComponent implements ControlValueAccessor {
  @ViewChild('inputRef')
  inputRef: ElementRef<HTMLInputElement>;
  changed: (value: any) => void;
  touched: () => void;
  isDisabled: boolean;

  writeValue(value: string): void {
    if (this.inputRef) {
      this.inputRef.nativeElement.value = value;
    }
  }

  ...
Run Code Online (Sandbox Code Playgroud)

另一个解决方案是使用ngModel然后它可以与value绑定到输入的属性一起使用。