Angular - 自定义输入:通过 form.reset() 重置触摸状态不起作用

问题描述 投票:0回答:2

我有一个关于重置带有自定义输入的表单的问题。

我将验证消息绑定到输入的 Touched 属性。 在默认输入上,form.reset() 还将触摸状态重置回 false,在自定义输入上,它不会转发。

我添加了一个plunkr https://plnkr.co/edit/ZyELDDFf3rxQRipHlWnb?p=preview来说明问题:触摸并离开两个控件,两个控件都被触摸:true,然后重置。 我如何将这个清除重置事件(将触摸状态恢复为 false)转发到我的自定义输入?

@Component({
selector: 'my-app',
template: `
    <p><span class="boldspan">Form data:</span>{{demoForm.value | json}}</p>
    <p><span class="boldspan">Model data:</span> {{dataModel}}</p>
    <form #demoForm="ngForm">
      <custom-input name="someValue" [(ngModel)]="dataModel">
        custom input
      </custom-input>
      <label>native input<br>
      <input type="text" [(ngModel)]="someOtherValue" name="someOtherValue"
      #sOV="ngModel"></label>
      <div>touched: {{sOV.touched}}</div>
    </form>
    <br>
    <button (click)="demoForm.reset()">Reset Form</button>`
})
export class App {
    dataModel: string = '';
}

谢谢并致以诚挚的问候

angular
2个回答
0
投票

这是我迄今为止使用的解决方案:


@Component({
  selector: 'custom-input',
  standalone: true,
  imports: [CommonModule, FormsModule],
  template: `<div class="form-group">
                    <label><ng-content></ng-content>
                        <input [(ngModel)]="value"  
                                class="form-control" 
                                (blur)="onBlur()"
                                #i="ngModel">
                        </label>
                        <div>touched: (custom-input) {{i.touched}}</div>
                </div>`,
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CustomInputComponent),
      multi: true,
    },
  ],
})
export class CustomInputComponent implements ControlValueAccessor, OnInit {
  private innerValue: any = '';

  private onTouchedCallback: () => void = () => null;
  private onChangeCallback: (_: any) => void = () => null;

  // 1 add injector
  constructor(private injector: Injector) {}

  // 2 prepare field to access ngcontrol of the custom-input.component and ngcontrol of the input in the template
  private model?: NgControl;
  @ViewChild('i') input?: NgControl;

  ngOnInit() {
    // 3 get ngcontrol of the custom-input.component
    this.model = this.injector.get(NgControl);

    if (this.model) {
      // 4 subscribe to custom-input ngcontrol's statusChange to sync both ngcontrols
      this.model.statusChanges?.subscribe(() => {
        if (!this.input || !this.model) return;
        if (this.model.touched !== this.input.touched)
          this.model.touched
            ? this.input.control?.markAsTouched()
            : this.input.control?.markAsUntouched();
      });
    }
  }

  get value(): any {
    return this.innerValue;
  }

  set value(v: any) {
    if (v !== this.innerValue) {
      this.innerValue = v;
      this.onChangeCallback(v);
    }
  }

  onBlur() {
    this.onTouchedCallback();
  }

  writeValue(value: any) {
    if (value !== this.innerValue) {
      this.innerValue = value;
    }
  }

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

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

这里是演示:https://stackblitz.com/edit/stackblitz-starters-yu8tda?file=src%2Fcustom-input.component.ts


-1
投票

使用

demoForm.resetForm()

而不是

demoForm.reset()
© www.soinside.com 2019 - 2024. All rights reserved.