Angular 2 Cross Field Validation (на основе модели) addErrors?

Я реализую кросс-полевую проверку для двух полей в форме (реактивный подход / подход на основе модели) и не знаю, как мне добавить ошибку в существующий список ошибок элемента управления формой.

Форма:

this.myForm = new FormGroup({
  name: new FormControl('', Validators.minLength(3));
  city: new FormGroup({
    cityOne: new FormControl('', Validators.minLength(3)),
    cityTwo: new FormControl('', Validators.minLength(3))
  }, this.validateEqualCities)
});

Валидатор:

validateEqualCities(formGroup: FormGroup) {
    return (control: AbstractControl): { [key: string]: any } => {
    if (formGroup.controls['cityOne'].value &&  formGroup.controls['cityTwo'].value && formGroup.controls['cityOne'].value !== formGroup.controls['cityTwo'].value) {

     formGroup.controls['cityOne'].setErrors({ 'equalCities': true }, { emitEvent: true });
     formGroup.controls['cityTwo'].setErrors({ 'equalCities': true }, { emitEvent: true });

        return { 'equalCities': false };

    } else {
      formGroup.controls['cityOne'].updateValueAndValidity({ onlySelf: true, emitEvent: false });
      formGroup.controls['cityTwo'].updateValueAndValidity({ onlySelf: true, emitEvent: false });
    }

    return null;
    };
  }

Моя проблема: если проверка не удалась, setErrors (..) отменяет все ошибки, которые уже есть (валидаторы formControls), поэтому нет правильного состояния, потому что на самом деле должно быть 2 ошибки.

Если я не устанавливаю ошибки для формирования элементов управления напрямую, а только возвращаю ошибку в форму, только форма является недействительной и получает ошибку, но не ее элементы управления.

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

Большое тебе спасибо!


person user3287019    schedule 08.12.2016    source источник


Ответы (1)


Вы можете зафиксировать объект ошибок в том виде, в каком он есть, прежде чем назначать ошибки, изменять его и записывать обратно весь объект.

validateEqualCities(formGroup: FormGroup) {
  return (control: AbstractControl): { [key: string]: any } => {
    if (formGroup.controls['cityOne'].value &&  formGroup.controls['cityTwo'].value && formGroup.controls['cityOne'].value !== formGroup.controls['cityTwo'].value) {
      let errors = formGroup.controls['cityOne'].errors ? formGroup.controls['cityOne'].errors : {};
      errors['equalCities'] = false;
      formGroup.controls['cityOne'].setErrors(errors, { emitEvent: true });

      errors = formGroup.controls['cityTwo'].errors ? formGroup.controls['cityTwo'].errors : {};
      errors['equalCities'] = false;

      formGroup.controls['cityTwo'].setErrors(errors, { emitEvent: true });

      return { 'equalCities': false };
    <...>

Вот Plunker с работающей демонстрацией: http://plnkr.co/edit/XTeH1ifQTJSoMvBEvE0d?p=preview

person silentsod    schedule 08.12.2016
comment
Выглядит хорошо, я подумал о решении и спросил себя, это похоже на какой-то взлом, нет другого более элегантного / нативного решения? Но тем не менее спасибо! - person user3287019; 08.12.2016
comment
Не совсем, нет никаких средств для добавления единственной ошибки, если вы делаете явный набор (и нет способа заставить групповые прикладные ошибки каскадировать вниз, о чем я знаю), так что это в значительной степени то, что вы получаете. - person silentsod; 08.12.2016