Когда Angular FormArray является традиционным массивом и когда это объект FormArray? - PullRequest
12 голосов
/ 11 июня 2019

Я создал пользовательский компонент ввода с ControlValueAccessor, и он прекрасно работает для добавления тегов в качестве выбора. ( Stackblitz )

Моя проблема:

  1. при реализации компонента в форме (элементы управления городами и штатами)
  2. добавить значения к обоим элементам управления, выбрав некоторые опции
  3. отправить форму
  4. иногда контрольное значение представляет собой массив выбранных тегов (как и ожидалось)
  5. в других случаях это фактический объект FormArray

Вот снимок экрана с двумя значениями одного и того же компонента после отправки угловой формы. Один - это массив объектов (ожидаемый), другой - это реальный объект FormArray, свойство .value которого содержит массив объектов!

enter image description here

Вот пример того, как это работает, если вы не хотите посещать StackBlitz.

Пользовательский элемент управления реализован следующим образом.

this.form = this.fb.group({
  tags: this.fb.array([])
});

Когда пользователь выбирает выпадающий элемент или нажимает кнопку ввода, объект сохраняется следующим образом:

get tagsArray(): FormArray { return this.form.get('tags') as FormArray; }
...
this.tagsArray.push(new FormControl(value));
this.onChange(this.tagsArray); // update controller value

Вы можете повторить это, реализовав компонент в моем StackBlitz в форме группы, например, (также в моем StackBlitz):

Форма инициации

public form: FormGroup = this.fb.group({
    states: [],
    cities: []
});

Template

<input-tags formControlName="cities" label="Cities" [typeAhead]="cities" [displayKeys]="['name']" filterKeys="['name']"></input-tags>
<input-tags formControlName="states" label="States" [typeAhead]="states" [displayKeys]="['name']" filterKeys="['name']"></input-tags>

но вопрос такой:

Когда Angular FormArray является традиционным массивом и когда это объект типа ArArray Array?

1 Ответ

4 голосов
/ 15 июня 2019

FormArray объект создается при создании экземпляра элемента управления с использованием new FormArray([]) или formBuilder.array([]).

Однако, если вы примените экземпляр FormControl к классу с помощью методов ControlValueAccessor, он будетзаписать FormControl или FormGroup (если вы хотите работать с предоставленными объектами формы Angular) в значение элемента управления, который вы передали.

Таким образом, в первом случае вы получаете объект FormArray иво втором случае вы можете получить либо обычные типы JS (объект, массив, строка и т. д.), либо FormGroup / FormControl.

Если вы хотите получить более расширенный ответ, специфичный для вашего случая, пример кода необходим, потому чтоВаша реализация может вызвать преобразование массива в FormArray в некоторый момент.

Обновление # 1

Если мы изменим valueChanges с users на form, мы увидим, что эта формаявляется неработоспособным, потому что .value дает нам еще один FormArray вместо простого массива.

enter image description here

Кроме того, я проверил реализацию иТам нет места, где вы можете получить обычный массив.Тем не менее, пользовательский элемент управления реализован неправильно ИМХО, так как вы должны указать значение .value вместо FormArray или что-либо подобное этому.

Поэтому, если вы можете изменить реализацию этого элемента управления, я бы предложил вамсделай это.Я делаю это в порядке

registerOnChange(fn: any): void {
  this.tagsArray.valueChanges.subscribe(fn);
}
...