简体   繁体   English

如何验证 angular 中的 formarray?

[英]How to validate formarray in angular?

I'm using editable with formarray.我正在使用带有formarray的可编辑。 My model:我的 model:

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

allBooks:所有书籍:

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

code snippet:代码片段:

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]
    }))
  });
}

I have to validate the book name, name is required and unique.我必须验证书名,名称是必需的并且是唯一的。 The html snippet: 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>

In this editable table, each row is formgroup.在这个可编辑的表格中,每一行都是 formgroup。 When after editing the name columns, this row will be saved.编辑名称列后,将保存该行。 Question is how to validate?问题是如何验证? In my case, only save one row in one time.就我而言,一次只能保存一行。 So should I validate all the formarray or just one formgroup in that formarray?那么我应该验证所有表单数组还是只验证该表单数组中的一个表单组? and how?如何?

You can choose to not have one big form and pass the form group for the row when you save and check if the row is valid before you save.您可以选择不使用一个大表单并在保存时传递该行的表单组,并在保存之前检查该行是否有效。 This will make your code easier to understand.这将使您的代码更容易理解。 Once you save, you will want to reset that form using this.form.markAsPristine() .保存后,您将需要使用this.form.markAsPristine()重置该表单。

You could achieve this with the big form by passing the row's form group into the save method as well.您也可以通过将行的表单组传递给 save 方法来使用大表单来实现这一点。

just a customValidator over the array.只是数组上的 customValidator 。 Anyway there're a type error in your code, take a look to stackblitz无论如何,您的代码中存在类型错误,请查看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" };
    };
  }

Update You can also create a validator only for the fields "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" };
    };
  }

And you create the form like然后你创建这样的表格

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()
      )
    });
  }

But the problem is that when change the name, not check the others name.但问题是更改名称时,不检查其他名称。 so you must create a function所以你必须创建一个 function

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

And call in the (input) of the edit -or subscribe to valuesChange-并调用编辑的(输入) - 或订阅 valuesChange-

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

Update how validate on submit or on blur更新提交或模糊时的验证方式

For validate on submit or blur, we need create the form with the constructor of formGroup and FormControl, not with FormBuilder adding {updateOn:'blur'} or {updateOn:'submit'} at the end of new FormGroup (*) in this case use (blur) in the input对于提交或模糊验证,我们需要使用 formGroup 和 FormControl 的构造函数创建表单,而不是使用 FormBuilder 在新 FormGroup (*) 的末尾添加{updateOn:'blur'}{updateOn:'submit'}输入中的案例使用(模糊)

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM