簡體   English   中英

Angular 2+ material mat-chip-list formArray 驗證

[英]Angular 2+ material mat-chip-list formArray validation

如何驗證mat-chip已添加到mat-chip-list 我正在使用 ReactiveForms。 我已嘗試使用required驗證器。

該值可以是姓名列表,因此在提交表單之前,我需要確保姓名列表中至少有 1 個姓名。 如果列表為空,則mat-error應顯示錯誤消息。 無論向列表中添加名稱,使用required驗證器都會使表單無效。

編輯:反應形式

我試圖制作一個自定義驗證器,我現在使用的是反應式表單而不是模板驅動的表單,但我無法讓它工作。 我編輯了以下代碼以反映我的更改,並創建了此https://stackblitz.com/edit/angular-4d5vfj

HTML

<form [formGroup]="myForm">
  <mat-form-field class="example-chip-list">
    <mat-chip-list #chipList formArrayName="names">
      <mat-chip *ngFor="let name of myForm.get('names').controls; let i=index;"
        [formGroupName]="i"
        [selectable]="selectable"
        [removable]="removable"
        (removed)="remove(myForm, i)">
        <mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
      </mat-chip>

       <input placeholder="Names"
          [matChipInputFor]="chipList"
          [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
          [matChipInputAddOnBlur]="addOnBlur"
          (matChipInputTokenEnd)="add($event, asset)">
    </mat-chip-list>
    <mat-error>Atleast 1 name need to be added</mat-error>
  </mat-form-field>
</form>

TS

import {COMMA, ENTER} from '@angular/cdk/keycodes';
import {Component} from '@angular/core';
import {FormGroup, FormControl, FormBuilder, FormArray} from '@angular/forms';
import {MatChipInputEvent} from '@angular/material';

@Component({
  selector: 'chip-list-validation-example',
  templateUrl: 'chip-list-validation-example.html',
  styleUrls: ['chip-list-validation-example.css'],
})
export class ChipListValidationExample {
  public myForm: FormGroup;

  // name chips
  visible = true;
  selectable = true;
  removable = true;
  addOnBlur = true;
  readonly separatorKeysCodes: number[] = [ENTER, COMMA];

  // data
  data = {
    names: ['name1', 'name2']
  }

  constructor(private fb: FormBuilder) {
    this.myForm = this.fb.group({
      names: this.fb.array(this.data.names, this.validateArrayNotEmpty)
    });
  }

  initName(name: string): FormControl {
    return this.fb.control(name);
  }

  validateArrayNotEmpty(c: FormControl) {
    if (c.value && c.value.length === 0) {
      return { 
        validateArrayNotEmpty: { valid: false }
      };
    }
    return null;
  }

  add(event: MatChipInputEvent, form: FormGroup): void {
    const input = event.input;
    const value = event.value;

    // Add name
    if ((value || '').trim()) {
      const control = <FormArray>form.get('names');
      control.push(this.initName(value.trim()));
      console.log(control);
    }

    // Reset the input value
    if (input) {
      input.value = '';
    }
  }

  remove(form, index) {
    console.log(form);
    form.get('names').removeAt(index);
  }
}

問題是當chipList 的FormArray狀態為INVALID時,ch​​ipList 的errorState未設置為true

我面臨着同樣的問題,不知道為什么這不是開箱即用的,或者如何通過 ChipList 的形式作為FormArray隱式實現這FormArray

作為一種解決方法,您可以從FormArray監聽狀態更改並手動設置chipList的errorState

@ViewChild('chipList') chipList: MatChipList;

ngOnInit() {
  this.myForm.get('names').statusChanges.subscribe(
    status => this.chipList.errorState = status === 'INVALID'
  );
}

https://stackblitz.com/edit/angular-4d5vfj-gywxjz

不幸的是,不能使用任何 Angular 的預定義驗證器,因為它們不是為處理數組而設計的。 在這篇文章的幫助下,我設法做到了:

https://www.dev6.com/Angular_Material_Chips_with_Reactive_Forms_and_Custom_Validation

為了能夠在mat-chip-list上進行驗證,我們必須使用相同的FormControl綁定mat-inputmat-chip-list ,如下所示

在這里工作 Stackblitz 鏈接

 <form [formGroup]='group'> <mat-form-field class="example-chip-list"> <mat-chip-list #chipList required formControlName="newFruit"> <mat-chip *ngFor="let fruit of fruits" (removed)="remove(fruit)"> {{fruit.name}} <mat-icon matChipRemove>cancel</mat-icon> </mat-chip> <input placeholder="New fruit..." formControlName="newFruit" [matChipInputFor]="chipList" [matChipInputSeparatorKeyCodes]="separatorKeysCodes" [matChipInputAddOnBlur]="addOnBlur" (matChipInputTokenEnd)="add($event)" required> </mat-chip-list> <!-- add mat-error --> <mat-error *ngIf="group.controls.newFruit.hasError('required')">required!</mat-error> </mat-form-field> </form>

正如mmalerba這個示例所示,您可以使用兩個單獨的表單控件:一個用於 mat-chip-list(這個應該是具有所需標志的那個),另一個用於輸入。 有趣的是,您必須在 addEvent 上手動設置兩者的值:

<!-- ... -->
    <mat-chip-list #chipList formControlName="names" required>
    <!-- ... -->
    <input placeholder="Names"
        [formControlName]="name"
        [matChipInputFor]="chipList"
        [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
        [matChipInputAddOnBlur]="addOnBlur"
        (matChipInputTokenEnd)="add($event, asset)">
    </mat-chip-list>
    <!-- ... -->
import {Validators} from '@angular/forms';

    # ...
    constructor(private fb: FormBuilder) {
        this.myForm = this.fb.group({
            names: [this.data.names, Validators.required],
            name: ['']
        });
    }

    # ...
    add(event: MatChipInputEvent, form: FormGroup): void {
      const input = event.input;
      const value = event.value;

      // Add name
      if ((value || '').trim()) {
        const control = <FormArray>form.get('names');
        control.push(this.initName(value.trim()));
        console.log(control);
      }

      // Reset the input value
      if (input) {
        input.value = '';
      }

      // update form control (necessary for correct validation)
      this.myForm.controls.name.setValue(null);
      this.myForm.controls.names.setValue(this.data.names);
    }

    # ...
}

這是他們的stackblitz 示例

因為有人正面臨這個問題。 幾個小時后,我找到了問題的根本原因和解決方案:

在chiplist的add、remove、select函數中,需要使用reactive形式的setValue函數來進行校驗。

例如:

  this.form.get('names').value.push('abc');
  this.form.get('names').setValue(this.form.get('names').value); // => this line of code will make the validation work

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM