Angular Reactive Form - Подпишитесь на экземпляры Form Control в массиве Form, чтобы получить общую стоимость - PullRequest
0 голосов
/ 21 мая 2018

Я использую Angular Reactive Forms для перебора массива значений. Я хотел бы иметь итоговое поле после массива форм, которое обновляет изменения значений элемента управления массива форм.

Пример данных:

  primaryData = {
    products: [
      {
        name: 'test-product',
        unmoved: 21,
        moved: 18 
      },
      {
        name: 'another-product',
        unmoved: 18,
        moved: 42
      }
    ]
  }

Я создаю элементы управления и массив Reactive Form следующим образом:

  setPrimaryQuantities() {
    const control = <FormArray>this.primaryForm.controls.quantities;
    this.primaryData.products.forEach(product =>
      control.push(this.fb.group({
        name: [product.name, Validators.required],
        unmoved: [product.unmoved, Validators.required],
        moved: [product.moved, Validators.required]
      }))
    )
  }

  ngOnInit() {
    this.primaryForm = this.fb.group({
      quantities: this.fb.array([]),
      unmovedTotal: '',
      movedTotal: ''
    })
    this.setPrimaryQuantities();
  }

Каков наилучший способ обновления элементов управления unmovedTotal и movedTotal на основе изменений вМассив контролирует.Вот StackBlitz , демонстрирующий мою структуру.

1 Ответ

0 голосов
/ 21 мая 2018

По моему мнению, итоговые данные не должны быть в форме.Он отключен без каких-либо условий в вашем Typescript, и я не могу представить вариант использования, в котором вы бы редактировали итоги напрямую.Это просто вычисленное значение из формы.

Тем не менее, было бы неплохо иметь наблюдаемый тип:

total$: Observable<{ moved: number, unmoved: number }>

Чтобы сделать это, так как вы использовалиРеактивная форма, это довольно просто:)

this.total$ = this.primaryForm.valueChanges.pipe(
  startWith(this.primaryForm.value),
  map(f => f.quantities.reduce(
    (acc, q) =>
    ({
      moved: acc.moved + q.moved,
      unmoved: acc.unmoved + q.unmoved
    }),
    { moved: 0, unmoved: 0 }
  ))
);

Каждый раз, когда форма меняется, вы хотите получить новые итоги.Если вы хотите создать новое значение (итоги) из исходного (значения формы), используйте оператор map.

В форме мы хотим выполнить цикл по количествам и получитьсумма для свойств moved и unmoved.Так что здесь мы не можем использовать map (базовая карта JS, а не карта из RXJS), потому что она создаст массив.Для этого мы можем использовать reduce (еще раз тот, что из чистого JS, здесь нет RXJS).

Теперь, когда у нас есть наша наблюдаемая, нам просто нужно использовать ее в представлении.Чтобы избежать двух подписок, мы можем использовать ngIf с синтаксисом as:

<tr *ngIf="total$ | async as total">
  <td>Totals</td>
  <td>{{ total.unmoved }}</td>
  <td>{{ total.moved }}</td>
</tr>

Вот полный пример, основанный на вашем первоначальном примере Stackblitz:

https://stackblitz.com/edit/angular-kbk3zm?file=src%2Fapp%2Fapp.component.ts

...