Angular ReactiveForms не получает динамического значения

Я использую реактивные формы в Angular, и у меня есть этот FormArray, из которого я получаю все значения, кроме product_total.

<tbody formArrayName="products">
  <tr *ngFor="let phone of productForms.controls; let i=index" [formGroupName]="i">
      <th scope="row">{{i+1}}</th>
      <td><input type="text" class="form-control" placeholder="Product Code" formControlName="product_code"></td>
      <td><input type="text" class="form-control" placeholder="Product Name" formControlName="product_name"></td>
      <td><input type="number" class="form-control" placeholder="Price" formControlName="product_price" #price></td>
      <td><input type="number" class="form-control"  formControlName="product_quantity" value="1" #quantity></td>
      <td><input type="number" class="form-control" value="{{(price.value || 0) * (quantity.value || 1)}}" formControlName="product_total" disabled></td>
    </tr>
  </tbody>

Как получить значение product_total для каждой группы форм внутри машинописного кода? P.S. Я получаю значение внутри HTML-кода, но не в машинописном коде.

Код машинописного текста:

constructor(private fb: FormBuilder) { }

ngOnInit() {
const product = this.fb.group({
  product_code: [],
  product_name: [],
  product_price: [],
  product_quantity: [1],
  product_total: []
});

this.myForm = this.fb.group({
  customer_name: '',
  customer_phone: '',
  customer_address: '',
  products: this.fb.array([product]),
  subtotal: Number,
  discount: Number,
  cgst: Number,
  sgst: Number,
  total_price: Number,
});
}

get productForms() {
  return this.myForm.get('products') as FormArray;
}


async submitForm() {
    const myForm = this.myForm.value;
    this.invoice = {
      products: myForm.products,
    };
    console.log(this.invoice.products);

  }

person Isurendrasingh    schedule 01.08.2018    source источник
comment
Если вы хотите всего, вы должны подписаться на valueChanges, см., например. alligator.io/angular/reactive-forms-valuechanges. Если только итог по строке, используйте {{phone.get('product_price').value *( phone.get('product_quantity').value ||1)}}   -  person Eliseo    schedule 01.08.2018
comment
@Элизео, это не то, о чем я спрашивал. Я получаю значение product_total внутри ввода формы, но не в машинописном коде. В машинописном коде я получаю null.   -  person Isurendrasingh    schedule 01.08.2018
comment
показать полную строку кода   -  person Ravindra Gupta    schedule 01.08.2018
comment
@SurendraSinghChhabra, посмотри мой ответ   -  person Eliseo    schedule 01.08.2018
comment
@SurendraSinghChhabra, можете ли вы добавить машинописный текст этого компонента?   -  person Muhammad Waqas Dilawar    schedule 01.08.2018
comment
@RavindraGupta Добавлено!   -  person Isurendrasingh    schedule 01.08.2018
comment
@WaqasDilawarDaha Добавлено!   -  person Isurendrasingh    schedule 01.08.2018


Ответы (2)


Отредактировано, в предыдущем коде есть {{ }}, но если мы используем [значение], вам не нужно ставить {{ }}, обновленный код

Вам не нужно, чтобы общее количество принадлежало formGroup

<input type="number" class="form-control" disabled
    [value]="phone.get('product_price').value *( phone.get('product_quantity').value)" >

в submit можно сделать карту, если считаете нужным

submit(form){
   if (form.valid)
   {
      let data={
             //all properties of for.value
             ...form.value,
             //but products was products "mappeated"
             products:form.value.products.map(v=>{
             return {
               //Which each product, return 
               ...v,   //all de properties of products +
               total:v.product_price*v.product_quantity  //total
          }})
        }

      console.log(data);
   }
person Eliseo    schedule 01.08.2018
comment
отображение работает, но не получает данные в массиве. то есть получение данных в консоли, но не в массиве - person Isurendrasingh; 01.08.2018
comment
@SurendraSinghChhabra, извините. Я написал [value]={{...}} и получил [value]=... (не заключенный в {{ }} ). Моя идея состоит в том, что formGroup НЕ имеет total. Если нам нужно общее количество для отправки в API или что-то еще, мы всегда можем при отправке формы создать общее количество свойств. - person Eliseo; 01.08.2018
comment
Понял! но все еще не работает. Пожалуйста, смотрите код машинописного текста, который я обновил, для получения дополнительной информации. Также {...v,total:vproduct_priceproduct_quantity} не определен, так как он находится в массиве форм, что также дает ошибку. - person Isurendrasingh; 01.08.2018
comment
@SurendraSinghChhabra, но обновите код, извините за задержку - person Eliseo; 01.08.2018
comment
Работающий!! Спасибо за ваши старания. - person Isurendrasingh; 02.08.2018

У меня была аналогичная логика для реализации. Я сделал это в контроллере, используя что-то вроде этого:

ngOnInit() {
    this.formGroup = this.formBuilder.group({
        price: ['', [Validators.required]],
        quantity: ['', [Validators.required]],
        total: ''
    });

    this.formGroup.valueChanges.subscribe(change => {
        this.priceChanges()
    })
}

priceChanges() {
    let price = parseFloat(this.formGroup.value.price);
    let quantity = parseInt(this.formGroup.value.quantity);

    if (!isNaN(price) && !isNaN(quantity)) {
        let totalCost = (price * quantity).toFixed(2);
        this.formGroup.controls['total'].setValue(totalCost, { emitEvent: false })
    }
}

Отредактированная версия для обработки FormArray:

Обратите внимание на добавленный (ngModelChange)="detectValueChange(i)" к двум вашим входам:

<tbody formArrayName="products">
    <tr *ngFor="let phone of productForms.controls; let i=index" [formGroupName]="i">
        <th scope="row">{{i+1}}</th>
        <td> <input type="text" class="form-control" placeholder="Product Code" formControlName="product_code"></td>
        <td> <input type="text" class="form-control" placeholder="Product Name" formControlName="product_name"></td>
        <td><input type="number" class="form-control" placeholder="Price" formControlName="product_price" #price (ngModelChange)="detectValueChange(i)"></td>
        <td><input type="number" class="form-control" formControlName="product_quantity" value="1" #quantity (ngModelChange)="detectValueChange(i)"></td>
        <td><input type="number" class="form-control" value="{{(price.value || 0) * (quantity.value || 1)}}" formControlName="product_total" disabled></td>
    </tr>
</tbody>

Затем аналогично моему исходному решению, но теперь с индексацией массива 'products'.

detectValueChange(index: number){
    let controls = this.formGroup.get('products') as FormArray;
    this.changeTotal(controls[index])
}

changeTotal(control) {
    let price = parseFloat(control.value.product_price);
    let quantity = parseInt(control.value.product_quantity);
    if (!isNaN(price) && !isNaN(quantity)) {
        let totalCost = (price * quantity).toFixed(2);
        control['product_total'].setValue(totalCost, { emitEvent: false })
    }
}
person Richard Dunn    schedule 01.08.2018
comment
будьте осторожны, 1. ваша функция priceChanges неверна. Вы должны использовать this.formGroup.get('price').value, а НЕ this.formGroup.value.price - см. в консоли разницу. 2.- так как прикрепите изменение ко всем изменениям в форме, при изменении итога снова зайдите в функцию - person Eliseo; 01.08.2018
comment
Вы совершенно правы! Я забыл добавить { emitEvent: false }, см. отредактированную версию. - person Richard Dunn; 01.08.2018
comment
использование этого подхода приводит к получению суммы только в первой группе форм, а не в других - person Isurendrasingh; 01.08.2018
comment
@SurendraSinghChhabra Не заметил FormArray. Смотрите мой отредактированный ответ (не проверен!). toFixed даст вам строку, поэтому, возможно, вы захотите обернуть ее в parseFloat. - person Richard Dunn; 01.08.2018
comment
@SurendraSinghChhabra Вы также можете что-то сделать, используя [formControlName] для доступа к вложенному FormControl. См. этот ответ: stackoverflow.com/a/48151444/4632627 - person Richard Dunn; 01.08.2018