Угловые ошибки проверки отображения FormArray - PullRequest
0 голосов
/ 31 августа 2018

У меня есть угловая форма, созданная с помощью FormBuilder.

Форма содержит FormArray, который имеет столько полей, сколько хочет пользователь. Я установил валидатор для полей

this.fb.array([this.fb.control('', Validators.required)])

и для каждого нового push валидатор одинаков.

Проблема в том, что я не знаю, как получить доступ к свойству isValid определенного поля, поскольку они связаны с FormControl через [formControlName]="index".

Я пытался сделать это таким образом, но, похоже, это не работает

<div *ngIf="array.at(index).invalid" class="alert alert-danger p-2">
</div>

Где array - это formArray.controls, переданный от родителя.

Обновление # 1

Есть чехол https://stackblitz.com/edit/angular-7ppkoh

Ответы [ 4 ]

0 голосов
/ 29 марта 2019

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

<div *ngIf="formGroup.get('features').controls[i].controls.index.invalid && (formGroup.get('features').controls[i].controls.index.dirty || formGroup.get('features').controls[i].controls.index.touched)"                                          class="text-center error">
<p [hidden]="!formGroup.get('features').controls[i].controls.index.errors.required">Index is required.</p>
</div>
0 голосов
/ 01 сентября 2018

Я не думаю, что это было бы возможно полностью на шаблоне. Это связано с тем, что для доступа к состоянию элемента управления FormArray в вашем шаблоне вам потребуется доступ к this.formGroup.get('features').controls[i].invalid. Но поскольку get возвращает экземпляр типа AbstractControl, у вас не будет доступа к массиву controls. Для этого вам нужно будет ввести все, что возвращено из this.formGroup.get('features') в FormArray. И я не думаю, что это возможно в шаблоне.

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

Так что, если мы продолжим ссылаться на ваш стек, например, вот как:

<form [formGroup]="formGroup">
  <div formArrayName="features">
    <div 
      class="row no-gutters form-group" 
      *ngFor="let feature of features.controls; let index = index; let last = last">
      <input 
        type="text" 
        class="form-control px-2 col" 
        [formControlName]="index" 
        title="feature" 
        required>

        IS Invalid - {{ getValidity(index) }}

      <div class="col-3 col-md-2 row no-gutters">
        <button 
          class="col btn btn-outline-danger" 
          (click)="removeFeature(index)">
          -
        </button>
        <button 
          class="col btn btn-success" 
          *ngIf="last" 
          (click)="addFeature()">
          +
        </button>
      </div>
    </div>
  </div>
</form>

А в вашем классе:

import { Component } from '@angular/core';
import { FormArray, FormBuilder, FormControl, Validators } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {

  constructor(
    private fb: FormBuilder,
  ) {}

  formGroup = this.fb.group({
    features: this.fb.array([this.fb.control('', Validators.required)])
  });

  get features(): FormArray {
    return this.formGroup.get('features') as FormArray;
  }

  addFeature(): void {
    this.features.push(this.fb.control('', Validators.required));
  }

  getValidity(i) {
    return (<FormArray>this.formGroup.get('features')).controls[i].invalid;
  }

  removeFeature(index): void {
    this.features.removeAt(index);
    console.log(this.features);
  }

}

UPDATE

Несколько месяцев назад я понял, что вызов метода в одном из синтаксисов привязки данных (т. Е. Интерполяция строки - {{ ... }}, привязка свойства - [propertyName]="methodName()" или привязка атрибута - [class.class-name]="methodName()" ИЛИ [style.styleName]="methodName()") Чрезвычайно дорого в плане производительности.

Итак, вы должны сделать это, используя:

{{ formGroup.controls['features'].controls[index].invalid }}

Вместо:

{{ getValidity(index) }}

Вот обновленный Рабочий образец StackBlitz для вашей ссылки.

0 голосов
/ 21 февраля 2019

В операторе ngFor вы определяете переменную «feature», которая будет использоваться для каждого элемента управления массива формы.

*ngFor="let feature of features.controls; let index = index; let last = last"

Вы можете использовать эту переменную, чтобы получить недопустимый статус этого элемента управления.

feature.invalid 

Вот Stackblitz


Дополнительно

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

Итак, это

<input type="text" class="form-control px-2 col" [formControlName]="index" title="feature" required>

Может быть

<input type="text" class="form-control px-2 col" [formControlName]="index" title="feature">
0 голосов
/ 01 сентября 2018

В классе FormGroup есть метод get, который возвращает abstractControl для данного ключа. Тот, который вы используете в formControlName.

Вот ссылки на оба документа Api:
AbstractControl
FormGroup

<form [formGroup]="form">
  <input formControlName="name" type="text" />
  <div *ngIf="form.get('name').invalid">
    <p><Message you like to show/p>
  </div>
</form>
...