首页 > 解决方案 > Angular 验证器不会被销毁

问题描述

我在选项卡中使用具有反应形式的组件。每次切换选项卡时,都会再次调用我的组件的验证器。这是我的组件:

import { Component, forwardRef, OnInit } from "@angular/core";
import {
  AbstractControl,
  FormBuilder,
  FormGroup,
  NG_VALIDATORS,
  NG_VALUE_ACCESSOR,
  ValidationErrors,
  Validator,
  Validators
} from "@angular/forms";

@Component({
  selector: "app-my-form",
  templateUrl: "./my-form.component.html",
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => MyFormComponent),
      multi: true
    },
    {
      provide: NG_VALIDATORS,
      useExisting: forwardRef(() => MyFormComponent),
      multi: true
    }
  ]
})
export class MyFormComponent implements Validator, OnInit {
  public form: FormGroup;
  constructor(fb: FormBuilder) {
    this.form = fb.group({
      name: [null, Validators.required]
    });
  }

  // ControlValueAccessor
  public writeValue(value: any): void {
    if (value) {
      this.form.patchValue(value, { emitEvent: false });
    }

    if (value === null) {
      this.form.reset();
    }
  }

  public registerOnChange(fn: any): void {
    this.form.valueChanges.subscribe(fn);
  }

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

  public setDisabledState?(isDisabled: boolean): void {
    isDisabled ? this.form.disable() : this.form.enable();
  }
  // ControlValueAccessor end

  // Validator
  validate(control: AbstractControl): ValidationErrors {
    console.log("validate");
    return null;
  }
  // Validator end

  public onTouched: () => void = () => {};

  ngOnInit() {}
}

我还做了一个stackblitz:https ://stackblitz.com/edit/angular-tab-test-hx71jy?file=src%2Fapp%2Fmy-form%2Fmy-form.component.ts

我究竟做错了什么?

标签: angularangular-reactive-forms

解决方案


问题是由于formControlName指令中的内存泄漏。作为一种解决方法,您可以将 destroyOnHide 输入属性设置为 false,以便隐藏组件而不是销毁。

<form [formGroup]="form">
  <ul ngbNav #nav="ngbNav" [(activeId)]="active" class="nav-tabs">
    <li [ngbNavItem]="1" [destroyOnHide]="false">
      <a ngbNavLink>One</a>
      <ng-template ngbNavContent>
        <app-my-form formControlName="tab1"></app-my-form>
      </ng-template>
    </li>
    <li [ngbNavItem]="2">
      <a ngbNavLink>Two</a>
      <ng-template ngbNavContent>
        <p>
          Lorem ipsum
        </p>
      </ng-template>
    </li>
  </ul>
</form>

推荐阅读