Как проверить формара в угловых? - PullRequest
0 голосов
/ 14 октября 2019

Я использую редактируемый с Formarray. Моя модель:

class Book {
  id: number;
  name: string;
  active: boolean;
}

все книги:

[
 {id: 1, name: 'book1', active: true},
 {id: 2, name: 'book2', active: true},
 {id: 3, name: 'book3', active: true},
]

фрагмент кода:

allBooks: Book[];
bookFg: FormGroup;

ngOnInit() {
  this.bookFg = this.fb.group({
    arrayForm: this.fb.array(allBooks.map(book => {
      id: [book.id],
      name: [book.name],
      active: [book.active]
    }))
  });
}

Я должен подтвердить название книги, имя является обязательным и уникальным. Фрагмент html:

<div class="data-container" [formGroup]="bookFg">
        <p-table id="resultTable" [columns]="cols" [value]="labelForm.get('arrayForm').controls" formArrayName="arrayForm" dataKey="value.id" scrollable="true" [resizableColumns]="true" scrollHeight="415px" selectionMode="single"
        [selection]="selected" (onRowSelect)="onRowSelect($event.data)">
          <ng-template pTemplate="header" let-columns>
            ...
            ...
            ...
          </ng-template>
          <ng-template pTemplate="body" let-rowData let-rowIndex="rowIndex">

            <tr [pSelectableRow]="rowData" [formGroupName]="rowIndex">
              <td>
                  <div class="text-center">
                    <input pInputText type="checkbox" formControlName="active">
                  </div>
              </td>
              <td pEditableColumn>
                  <p-cellEditor>
                      <ng-template pTemplate="input">
                          <input (focus)="onFocusEvent(rowIndex)" (blur)="onBlurEvent()" pInputText type="text" formControlName="name">
                      </ng-template>
                      <ng-template pTemplate="output">
                          {{rowData.get('name').value}}
                      </ng-template>
                  </p-cellEditor>
              </td>

            </tr>
          </ng-template>
        </p-table>
    </div>

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

Ответы [ 2 ]

1 голос
/ 14 октября 2019

просто customValidator над массивом. В любом случае в вашем коде есть ошибка типа, посмотрите на stackblitz

ngOnInit() {
    this.bookFg = this.fb.group({
      arrayForm: this.fb.array(
        this.allBooks.map(book =>
          this.fb.group({
            id: [book.id],
            name: [book.name],
            active: [book.active]
          })
        )
      )
    });
  }

  myCustomValidator() {
    return (formArray: FormArray) => {
      let valid: boolean = true;
      formArray.value.forEach((x, index) => {
        if (formArray.value.findIndex(y => y.name == x.name) != index)
          valid = false;
      });
      return valid ? null : { error: "Names must be unique" };
    };
  }

Обновление Вы также можете создать валидатор только для полей "name"

myCustomValidatorName(index) {
    return (formControl: FormControl) => {
      let valid: boolean = true;
      if (index) {
        const formArray =
          formControl.parent && formControl.parent.parent
            ? (formControl.parent.parent as FormArray)
            : null;
        if (formArray) {
          console.log(formControl.value);
          formArray.value.forEach((x, i) => {
            if (x.name == formControl.value && index>i) valid = false;
          });
        }
      }
      return valid ? null : { error: "Names must be inique" };
    };
  }

И вы создаете форму, подобную

ngOnInit() {
    this.bookFg = this.fb.group({
      arrayForm: this.fb.array(
        this.allBooks.map((book, i) =>
          this.fb.group({
            id: new FormControl(book.id),
            name: new FormControl(book.name, this.myCustomValidatorName(i)),
            active: new FormControl(book.active)
          })
        ),
        this.myCustomValidator()
      )
    });
  }

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

checkArray(index) {
    (this.bookFg.get("arrayForm") as FormArray).controls.forEach((x, i) => {
      if (i != index) x.get("name").updateValueAndValidity();
    });
  }

и вызвать (вход) редактирования - или подписаться на valuesChange-

  <input formControlName="name" (input)="checkArray(i)">

Обновить как проверить наsubmit или on blur

Для проверки при submit или blur нам нужно создать форму с конструктором formGroup и FormControl, а не с FormBuilder, добавив {updateOn:'blur'} или {updateOn:'submit'} в конце новой FormGroup (*)в этом случае используйте (размытие) на входе

this.bookFg = new FormGroup({
      arrayForm: new FormArray(
        this.allBooks.map((book, i) =>
          this.fb.group({
            id: new FormControl(book.id),
            name: new FormControl(book.name,this.myCustomValidatorName(i)),
            active: new FormControl(book.active)
          })
        ),
        this.myCustomValidator()
      )
    },{updateOn: 'blur'}); //<--this
0 голосов
/ 14 октября 2019

Вы можете выбрать не иметь одну большую форму и передавать группу форм для строки при сохранении и проверять, является ли строка действительной перед сохранением. Это облегчит ваш код. После сохранения вы захотите сбросить эту форму, используя this.form.markAsPristine().

Этого можно добиться с помощью большой формы, передав группу форм строки в метод сохранения.

...