1

我正在使用带有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>

在这个可编辑的表格中,每一行都是 formgroup。编辑名称列后,将保存该行。问题是如何验证?就我而言,一次只能保存一行。那么我应该验证所有表单数组还是只验证该表单数组中的一个表单组?如何?

4

2 回答 2

3

只是数组上的 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" };
    };
  }

更新您还可以仅为“名称”字段创建验证器

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)">

更新提交或模糊时的验证方式

为了验证提交或模糊,我们需要使用 formGroup 和 FormControl 的构造函数创建表单,而不是使用 FormBuilder 添加{updateOn:'blur'}{updateOn:'submit'}在新 FormGroup (*) 的末尾在这种情况下在输入中使用 (blur)

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
于 2019-10-14T06:38:15.207 回答
0

您可以选择不使用一个大表单并在保存时传递该行的表单组,并在保存之前检查该行是否有效。这将使您的代码更容易理解。保存后,您将需要使用this.form.markAsPristine().

您也可以通过将行的表单组传递给 save 方法来使用大表单来实现这一点。

于 2019-10-14T04:55:08.637 回答