Умножьте два элемента (столбцы, например, количество * unitPrice = enterGrossAmount) в таблице mat [dataSource], используя реактивные формы - PullRequest
0 голосов
/ 01 мая 2020

Есть ли у вас какие-либо идеи о том, как это сделать в Angular Реактивные формы с использованием Mat-Table и источника данных «Умножьте два элемента (столбцы, например, количество * unitPrice = enterGrossAmount) в mat-таблице [dataSource], используя реактивные формы»

    <ng-container matColumnDef="quantity">
                  <mat-header-cell *matHeaderCellDef style="direction: rtl">
                    <h6><b>Quantity</b></h6>
                  </mat-header-cell>
                  <mat-cell *matCellDef="let element " [formGroup]="element">
                    <mat-form-field floatLabel="never" appearance="none" style="text-align: right">
                      <input #quantity matInput type="text" matInput placeholder="" formControlName="quantity" autocomplete="off" appOnlyNumber>
                    </mat-form-field>
                  </mat-cell>
                </ng-container>

                <ng-container matColumnDef="unitPrice">
                  <mat-header-cell *matHeaderCellDef style="direction: rtl">
                    <h6><b>Unit Price</b></h6>
                  </mat-header-cell>
                  <mat-cell *matCellDef="let element " [formGroup]="element">
                    <mat-form-field floatLabel="never" appearance="none" style="text-align: right">
                      <input matInput  formControlName="unitPrice" autocomplete="off"
                      id="digit-only-decimal"
                      type="text"
                      digitOnly
                      decimal="true"
                      placeholder="0.00"
                      pattern="[0-9]+([\.][0-9]+)?">
                    </mat-form-field>
                  </mat-cell>
                </ng-container>

                <ng-container matColumnDef="enteredGrossAmount">
                  <mat-header-cell *matHeaderCellDef style="direction: rtl">
                    <h6><b>Gross Amount</b></h6>
                  </mat-header-cell>
                  <mat-cell *matCellDef="let element " [formGroup]="element">
                    <mat-form-field floatLabel="never" appearance="none" style="text-align: right">
                      <input matInput type="text" matInput placeholder="" formControlName="enteredGrossAmount" autocomplete="off">
                    </mat-form-field>
                  </mat-cell>
                </ng-container>

это части моих компонентов, выпущенные в formgrou и массивы форм
FormGroup

billingRegisterForm = this.formBuilder.group({
    id: [null],
    billDate: [new Date(), [Validators.required]],
    currencyRate: [{ value: this.decimalPipe.transform(0, '1.2-2'), disabled: true }],
    description1: [null, [Validators.required]],
    enteredAmount: [{ value: this.decimalPipe.transform(0, '1.2-2'), disabled: true }],
    documentTypeId: [null, [Validators.required]],
    sequenceNo: [null, [Validators.required]],
    creditTermId: [null, [Validators.required]],
    currencyId: [null, [Validators.required]],
    customerId: [null, [Validators.required]],
    taxClassId: [null, [Validators.required]],
    active: [{ value: true, disabled: true }],
    registerDetails: this.formBuilder.array([])
  });

     FormaArray

onAddRegisterDetail() {

    this.billingRegisterArray = <FormArray>this.billingRegisterForm.get('registerDetails');
    const grp = this.formBuilder.group({
      id: [null],
      quantity: [1, [Validators.required, Validators.min(1), Validators.min(1)]],
      unitPrice: [0.00, [Validators.required, Validators.pattern(this.mobnumPattern)]],
      enteredGrossAmount: [{ value: 0.00, disabled: true }, Validators.required],
      discountRate: [0.00, Validators.required],
      enteredDiscountAmount: [{ value: 0.00, disabled: true }, Validators.required],
      enteredNetAmount: [{ value: 0.00, disabled: true }, Validators.required],
      description1: [null, Validators.required],
      flexFieldCombinationId: ['', Validators.required],
      uomId: [null, Validators.required],
      taxClassId: [null, Validators.required]
    });
    this.billingRegisterArray.push(grp);
    this.billingRegisterForm.setControl('registerDetails', this.billingRegisterArray);
    this.dataSource = new MatTableDataSource((
      this.billingRegisterForm.get('registerDetails') as FormArray).controls);
  }



<ng-container matColumnDef="delete">
                      <mat-header-cell *matHeaderCellDef style="direction: rtl">
                        <h6><b>Delete</b></h6>
                      </mat-header-cell>
                      <mat-cell class="text-center" *matCellDef="let element ; let i = index">
                        <button type="button"  horizontal-align: right mat-icon-button color="warn"
                          (click)="onDelete(i)" [disabled]="this.buttonDisable">
                          <mat-icon [ngStyle]="{'color':'warning'}" class="mat-18">delete</mat-icon>
                        </button>
                      </mat-cell>>
                    </ng-container>

1 Ответ

1 голос
/ 01 мая 2020

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

onAddRegisterDetail() {

    this.billingRegisterArray = <FormArray>this.billingRegisterForm.get('registerDetails');
    const grp = this.formBuilder.group({
      id: [null],
      quantity: [1, [Validators.required, Validators.min(1), Validators.min(1)]],
      unitPrice: [0.00, [Validators.required, Validators.pattern(this.mobnumPattern)]],
      enteredGrossAmount: [{ value: 0.00, disabled: true }, Validators.required],
      discountRate: [0.00, Validators.required],
      enteredDiscountAmount: [{ value: 0.00, disabled: true }, Validators.required],
      enteredNetAmount: [{ value: 0.00, disabled: true }, Validators.required],
      description1: [null, Validators.required],
      flexFieldCombinationId: ['', Validators.required],
      uomId: [null, Validators.required],
      taxClassId: [null, Validators.required]
    });

    // get the controls
    const quantityCtrl = grp.get('quantity');
    const priceCtrl = grp.get('unitPrice');
    const grossAmtCtrl = grp.get('enteredGrossAmount');
    // combine value changes, start one with initial value
    combineLatest(
      quantityCtrl.valueChanges.pipe(startWith(quantityCtrl.value)), 
      priceCtrl.valueChanges.pipe(startWith(priceCtrl.value)) // may need to coerce type with map
    ).subscribe(([quantity, unitPrice]) => grossAmtCtrl.setValue(quantity * unitPrice)) // may need to format

    this.billingRegisterArray.push(grp);

    // you should only set the control and data source once
    // this.billingRegisterForm.setControl('registerDetails', this.billingRegisterArray);
    // this.dataSource = new MatTableDataSource((
      this.billingRegisterForm.get('registerDetails') as FormArray).controls);
}

this должен быть безопасным и не вызывать утечек памяти, так как все локально и должен собирать мусор нормально, но если вы хотите быть в безопасности, добавьте некоторое свойство контроллера, например:

private grossAmtSubs: Subscription[] = []

и pu sh подписки на него :

this.grossAmtSubs.push(
  combineLatest(
    ...
  ).subscribe( ... )
);

и добавьте хук ngOnDestroy для отмены подписки.

ngOnDestroy() {
  this.grossAmtSubs.forEach(s => s.unsubscribe())
}

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

также, если у вас есть функция удаления элемента, вы также можете попытаться отписаться там ...

onDelete(i: index) {
  const registerDetails = <FormArray>this.billingRegisterForm.get('registerDetails');
  registerDetails.removeAt(i);
  this.grossAmtSubs[i].unsubscribe();
  this.grossAmtSubs.splice(i,1);

}

изменить ... если вы хотите суммировать, подписаться на изменения массива где-то, как ...

this.billingRegisterForm.get('registerDetails').valueChanges.pipe(
  map(values => values.reduce((total, value) => total += value.enteredGrossAmount, 0)),
  distinctUntilChanged()
).subscribe(total => console.log('do whatever with the total: ', total))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...