Angular 6 - dynamiczne przeliczanie brutto - netto

0

Mam w aplikacji 4 pola:
netValue x quantity x vatRate = grossValueAdded
i chciałbym zrobić tak, żeby w przypadku zmiany jednej z nich pozostałe pola aktualizowały się dynamicznie (czyli zmieniając netValue, quantity lub vatRate aktualizowała się wartość grossValueAdded, a aktualizując grossValueAdded zmieniała się netValue). Wymyśliłem coś takiego jak poniżej i zasadniczo to działa oprócz sytuacji, w której przeliczam z grossValueAdded na netValue, bo wtedy prawdopodobnie ze względu na zaokrąglenia te wartości zaczynają w nieskończonej pętli maleć do zera. W jaki sposób wytłumić te zmiany?

        this.subscriptionServiceItemForm.controls["netValue"].valueChanges.pipe(
            debounceTime(100))
          .subscribe((ngModelChange) => {
              this.subscriptionServiceItem.grossValueAdded = this.roundUp((this.subscriptionServiceItem.netValue * this.subscriptionServiceItem.quantity) * (1 + (this.subscriptionServiceItem.vatRate / 100)));
            });

        this.subscriptionServiceItemForm.controls["quantity"].valueChanges.pipe(
            debounceTime(100))
            .subscribe((ngModelChange) => {
              if (Number.isInteger(this.subscriptionServiceItem.quantity))
                this.subscriptionServiceItem.grossValueAdded = this.roundUp((this.subscriptionServiceItem.netValue * this.subscriptionServiceItem.quantity) * (1 + (this.subscriptionServiceItem.vatRate / 100)));
            });

        this.subscriptionServiceItemForm.controls["vatRate"].valueChanges.pipe(
            debounceTime(100))
            .subscribe((ngModelChange) => {
              this.subscriptionServiceItem.grossValueAdded = this.roundUp((this.subscriptionServiceItem.netValue * this.subscriptionServiceItem.quantity) * (1 + (this.subscriptionServiceItem.vatRate / 100)));
            });

        this.subscriptionServiceItemForm.controls["grossValueAdded"].valueChanges.pipe(
            debounceTime(100))
          .subscribe((ngModelChange) => {
            //this.subscriptionServiceItemForm.controls['netValue'].patchValue(this.subscriptionServiceItemForm.controls['netValue'].value, { emitEvent: false });
              this.subscriptionServiceItem.netValue = this.subscriptionServiceItem.grossValueAdded / (1 + (this.subscriptionServiceItem.vatRate / 100)) / this.subscriptionServiceItem.quantity;
            //this.subscriptionServiceItemForm.controls['netValue'].patchValue(this.subscriptionServiceItemForm.controls['netValue'].value, { emitEvent: true });
            });
0

Spróbuj podmontować event handler na akcję w DOMie, np. (change).

0

W jaki sposób będzie się to lepsze od obecnego kodu?

0

Wtedy handlery nie powinny reagować na siebie nawzajem i unikniesz tego całego łańcucha zmian.

0

bo wtedy prawdopodobnie ze względu na zaokrąglenia te wartości zaczynają w nieskończonej pętli maleć do zera

Zdebugowałeś to? Co się dzieję w wypadku gdy przeliczasz w ten sposób i jak dalej zachowuje się kod? Czy subskrybcję w jakiś sposób nie wywołują się nawzajem, albo jakaś wartość, która chcesz podzielić jest niewłaściwa?

0

Zdebugowałem o tyle, że zaokrąglenie nie ma wpływu na działanie. Subskrypcje wywołują się nawzajem, bo muszą skoro to jest przeliczanie równania od lewej do prawej i od prawej do lewej. Wpadłem jeszcze na pomysł, żeby użyć filer() i podczas aktualizacji w jednej subskrypcji filtrować wszystkie inne zdarzenia i niby się kompiluje i działa, ale problem nie ustąpił:

        this.subscriptionServiceItemForm.controls["netValue"].valueChanges.pipe(
            filter(() => { return !this.suppresNetValue; }), debounceTime(100))
              .subscribe((ngModelChange) => {
                console.log("netValue lock");
                  this.suppresNetValue = true;
                  this.suppressGrossValueAdded = true;
                  this.subscriptionServiceItem.grossValueAdded = this.roundUp((this.subscriptionServiceItem.netValue * this.subscriptionServiceItem.quantity) * (1 + (this.subscriptionServiceItem.vatRate / 100)));
                  this.suppressGrossValueAdded = false;
                this.suppresNetValue = false;
                console.log("netValue unlock");
                });


        this.subscriptionServiceItemForm.controls["grossValueAdded"].valueChanges.pipe(
            filter(() => { return !this.suppressGrossValueAdded; }), debounceTime(100))
              .subscribe((ngModelChange) => {
                console.log("grossValueAdded lock");
                this.suppresNetValue = true;
                this.suppressGrossValueAdded = true;
                this.subscriptionServiceItem.netValue = this.subscriptionServiceItem.grossValueAdded / (1 + (this.subscriptionServiceItem.vatRate / 100)) / this.subscriptionServiceItem.quantity;
                this.suppressGrossValueAdded = false;
                this.suppresNetValue = false;
                console.log("grossValueAdded unlock");
              });
0

W sumie wyszło, że kod jest prawie dobry, ale trzeba ten fragment:

                  this.suppressGrossValueAdded = true;
                  this.subscriptionServiceItem.grossValueAdded = this.roundUp((this.subscriptionServiceItem.netValue * this.subscriptionServiceItem.quantity) * (1 + (this.subscriptionServiceItem.vatRate / 100)));
                  this.suppressGrossValueAdded = false;

wykonać synchronicznie. Chaining dwóch metod da się wykonać przez then(). A jak w Typescripcie wykonuje się to dla trzech?

1 użytkowników online, w tym zalogowanych: 0, gości: 1