Угловая форма изначально недопустима, когда содержит допустимый пользовательский компонент

У меня есть простой Angular (v8.0) компонент, который просто содержит вход с required набором атрибутов. У меня есть управляемая шаблоном форма, которая содержит этот компонент и привязывает его к начальному значению. Когда приложение запускается, статус ввода действителен, поскольку он привязан к начальному значению. Но форма неверно неверна. После внесения каких-либо изменений во входное значение состояние формы будет правильным и с тех пор остается правильным.

Я возвращаю статус проверки входных данных в моей реализации метода validate и это, похоже, является источником проблемы. Это работает правильно, если я возвращаю объект, который я строю сам, основываясь на текущем значении элемента управления. Однако я бы предпочел этого избежать, потому что в будущем мне понадобятся другие состояния проверки, и я не хочу проверять их все вручную.

Я попытался добавить вызовы updateValueAndValidity в различных местах кода, но это не имеет никакого эффекта.

Как сделать так, чтобы начальный статус проверки формы учитывал статус вложенного пользовательского компонента?

Вот код для компонента:

import { AfterViewInit, Component, ViewChild } from "@angular/core";
import { ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS, FormControl, Validator, NgModel } from "@angular/forms";

@Component({
  selector: "my-input",
  template: '<input [(ngModel)]="value" required #model="ngModel" />',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: MyInputComponent,
      multi: true
    },
    {
      provide: NG_VALIDATORS,
      useExisting: MyInputComponent,
      multi: true
    }
  ]
})
export class MyInputComponent implements ControlValueAccessor, Validator {
  onChange: any = () => {};
  onTouch: any = () => {};

  @ViewChild("model", { static: true }) model: NgModel;

  private _value: string = "";

  set value(x: string) {
    if (this._value !== x) {
      this._value = x;
      this.onChange(x);
    }
  }
  get value() {
    return this._value;
  }

  writeValue(obj: any): void {
    this.value = obj;
  }
  registerOnChange(fn: any): void {
    this.onChange = fn;
  }
  registerOnTouched(fn: any): void {
    this.onTouch = fn;
  }

  validate(c: FormControl) {
    return this.model.errors;
    //return this.value ? null : { required: true }; // this works!
  }
}

А вот код для внешней формы, которая содержит его:

import { Component } from "@angular/core";

@Component({
  selector: "my-app",
  template: `
    <form #frm="ngForm">
      <my-input [(ngModel)]="myValue" name="myInput"></my-input>
    </form>
  `
})
export class AppComponent {
  myValue: string = "hello";
}

Вот StackBlitz: https://stackblitz.com/edit/angular-lp3xpa . Добавьте или удалите символ для ввода, и статус формы изменится на действительный.

Всего 1 ответ


Это похоже на ту же проблему, что и этот вопрос , который предлагает обходной путь ручного запуска другой проверки из writeValue с использованием setTimeout . Кажется, это решает проблему.

В MyInputComonent :

  writeValue(obj: any): void {
    this.value = obj;
    setTimeout(() => { this.onChange(this.value); }, 0);
  }

Смотрите здесь

Но это похоже на взлом.


Есть идеи?

10000