Как настроить Angular Material Chip Contol с реактивными формами

У меня угловая реактивная форма с угловыми материалами

Для всех своих элементов управления я добавляю требуемый валидатор.

Я не уверен, как правильно настроить контроль чипов с реактивными формами.

Где вы устанавливаете formControlName, чтобы запускался требуемый валидатор? На данный момент я установил его в поле ввода, что, как я предполагаю, неверно.

Я просто хочу, чтобы courseIds была разделенной запятыми строкой с идентификаторами курса.

TS:

form: FormGroup;

ngOnInit() {
    this.form = new FormGroup({
      name: new FormControl("", [Validators.required]),
      courseIds: new FormControl("", Validators.required)
    });
  }

HTML:

  <form [formGroup]="form" (ngSubmit)="submit()">

    <mat-form-field>
      <input matInput type="text" formControlName="name" placeholder="Name">
    </mat-form-field>

    <mat-form-field>
      <mat-chip-list #chipList>
        <mat-chip *ngFor="let cid of courseIds" (removed) = "...">
          {{cid}}
        </mat-chip>

        <input matInput formControlName="courseIds"
               [matChipInputFor]="chipList" 
               placeholder="Ids" 
               (matChipInputTokenEnd)="add($event)">
      </mat-chip-list>
   </mat-form-field>    

....

    <button type="submit">OK</button>
  </form>

person Sun    schedule 07.06.2019    source источник
comment
Чипы не являются компонентами сами по себе: они просто отображают значение с заданным стилем. Подводя итог, вы бы хотели, чтобы ваши чипы отображали значение ввода, которое представляет собой строку с запятыми?   -  person    schedule 07.06.2019
comment
Что-то вроде этого?   -  person    schedule 07.06.2019
comment
Нет, у меня все работает нормально. Мне нужно, чтобы элемент управления микросхемой не прошел проверку (обязательно), если микросхемы не выбраны. Итак, где мне установить formControlName?   -  person Sun    schedule 07.06.2019
comment
ну ладно, тогда посмотрите блиц еще раз, скажите, подходит ли вам!   -  person    schedule 07.06.2019


Ответы (2)


Попробуйте установить formControlName на уровне <mat-chip-list>.

В вашем шаблоне установите ngFor для перебора контрольного значения courseIds

<mat-form-field>
    <mat-chip-list #chipList formControlName="courseIds">
        <mat-chip *ngFor="let cid of form.get('courseIds').value" (removed) = "...">
            {{cid}}
        </mat-chip>

        <input matInput
            [matChipInputFor]="chipList" 
            placeholder="Ids" 
            (matChipInputTokenEnd)="add($event)">
    </mat-chip-list>
</mat-form-field>

Затем в своем компоненте создайте группу форм с начальными значениями для courseIds, если они есть, иначе используйте пустой массив [] (поскольку чипы отображают массив, а не строку). В вашей функции add() и remove() добавьте и удалите значения из courseIds контрольного значения соответственно.

form: FormGroup;

ngOnInit() {
    this.form = new FormGroup({
        name: new FormControl("", [Validators.required]),
        courseIds: new FormControl([], Validators.required)
    });
}

add() {
    ...

    // Add new input to courseIds control value
    this.courseIds.value.push(value);

    this.courseIds.updateValueAndValidity();
}

remove() {
    ...

    // Remove element from control value array
    this.courseIds.value.splice(index, 1);    // where index = index of removed element

    this.courseIds.updateValueAndValidity();
}

// use getter method to access courseIds control value easily
get courseIds() { 
    return this.form.get('courseIds');
}
person nash11    schedule 07.06.2019
comment
опередите меня, вот рабочий пример stackblitz.com/edit/angular-9gjwo4 - person than; 07.06.2019
comment
Это должен быть принятый ответ, но обратите внимание, что пример stackblitz от @than лучше, поскольку у него нет атрибута formControlName в элементе input. Наличие этого атрибута вызывает ошибки при вводе во входные данные, потому что чипы визуализируются путем итерации по значению FormControl. - person Netanel Draiman; 24.02.2020
comment
@Nexaddo - Спасибо, что указали на это. Я набрал свой ответ, значит, я его пропустил. В моем коде было 2 formControlName. Я обновил свой ответ. - person nash11; 24.02.2020
comment
@ чем, ты легенда! - person Alex Klaus; 18.02.2021

При объединении FormArrays с nash11 его ответ не сработает. У меня была проблема, когда я редактировал другой formArray в той же группе форм, изменения в списке мат-чипов терялись.

Поэтому вот мое решение, как использовать управление микросхемой материала с реактивными формами + массивом форм.

https://stackblitz.com/edit/angular-9gjwo4-h4f9ux?file=app/chips-input-example.ts

микросхемы-input-example.html:

<form [formGroup]="form">

    <mat-form-field class="example-chip-list">
        <mat-chip-list #chipList aria-label="Fruit selection" formArrayName="fruits">
            <mat-chip *ngFor="let fruit of fruitControls.value" [selectable]="selectable" [removable]="removable"
                (removed)="remove(fruit)">
                {{fruit}}
                <mat-icon matChipRemove *ngIf="removable">cancel</mat-icon>
            </mat-chip>
            <input placeholder="New fruit..."
           [matChipInputFor]="chipList"
           [matChipInputSeparatorKeyCodes]="separatorKeysCodes"
           [matChipInputAddOnBlur]="addOnBlur"
           (matChipInputTokenEnd)="add($event)">
  </mat-chip-list>
    </mat-form-field>
</form>

чипы-input-example.ts

import { COMMA, ENTER } from "@angular/cdk/keycodes";
import { Component } from "@angular/core";
import { MatChipInputEvent } from "@angular/material/chips";
import {
  FormControl,
  FormGroup,
  FormGroupDirective,
  NgForm,
  Validators,
  FormBuilder,
  FormArray
} from "@angular/forms";

/**
 * @title Chips with input
 */
@Component({
  selector: "chips-input-example",
  templateUrl: "chips-input-example.html",
  styleUrls: ["chips-input-example.css"]
})
export class ChipsInputExample {
  visible = true;
  selectable = true;
  removable = true;
  addOnBlur = true;
  readonly separatorKeysCodes: number[] = [ENTER, COMMA];
  form: FormGroup;

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      fruits: this.fb.array(["Lemon", "Lime", "Apple"], Validators.required)
    });
  }

  get fruitControls(): FormArray {
    return this.form.controls.fruits as FormArray;
  }

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

    // Add our fruit
    if ((value || "").trim()) {
      this.fruitControls.push(this.fb.control(value));
    }

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

  remove(fruit: string): void {
    const index = this.fruitControls.value.indexOf(fruit);
    if (index >= 0) {
      this.fruitControls.removeAt(index);
    }
  }
}
person Michael Vonck    schedule 30.11.2020