Множество форм Angular Reactive и один сервис, который зависит от них всех

По сути, я пытаюсь воспроизвести поведение электронной таблицы. У меня есть несколько реактивных форм, каждая из которых касается определенного раздела общего расчета. И одни исходные данные влияют на ценность других. Для упрощения возьмем этот пример.

Форма A содержит информацию о ссуде, включая процентную ставку. Форма B содержит банковскую информацию, включая платеж по ссуде. Форма C показывает итоговые суммы по различным категориям расходов (не только по кредитам). Когда ставка изменяется в A, мне нужно обновить платеж по кредиту в B, что обновит итоги в C.

Если бы это было все, я думаю, мое решение было бы простым. Однако загвоздка в том, что у меня есть служба для обработки общих вычислений. Каждая форма вычисляет свои собственные итоги и передает их в службу. Сервис производит «основной расчет» и исправляет реактивные формы.

Таким образом, форма A изменяется, вызывая событие «valueChanges», которое запускает основной расчет службы. Основной расчет обновляет итоги в C и поля в форме B. Теперь B необходимо пересчитать свои промежуточные итоги. Когда B завершит свои промежуточные итоги, необходимо снова запустить основной расчет службы для обновления C. Проницательный с вашей стороны уловит бесконечный цикл, который ждет впереди, если я не использую:

{ emitEvent: false }

с моим вызовом patchValues.

Я новичок в реактивных формах и концепции разделения формы и данных. Это легко сделать, когда в сервисе есть все поля, и я использую ngModel для ввода; поменять услугу, поменять форму.

Я надеюсь, что кто-то, кто является экспертом в этой парадигме разделения данных, прольет свет на то, как я могу достичь своей цели. При необходимости я бы принял совершенно новый подход. Идея, опять же, состоит в том, чтобы воспроизвести функциональность электронных таблиц с модульными разделами данных (позволяя банковской информации, расходам и итоговым данным сохранять свою автономность).

По запросу я добавил часть кода.

/*  When any form changes, it updates the service
It then triggers the calculate function so that the relevant fields are 
updated.
*/

/* Form A */
onFormChange() {
    const formVals = this.loanForm.getRawValue(); // one of the values is the loan rate
    this.calcSubTotals(); // adds up the relevant fields in each loan. 
    for(const formFieldKey of Object.keys(formVals)) {
        this.calculationService[formFieldKey] = formVals[formFieldKey]
    }
    this.calculationService.calculate();
}

/* Form B */
onFormChange() {
    const formVals = this.bankForm.getRawValue();
    this.calcSubTotals(); // adds up the fields in each account. One of those fields is a loan payment that is updated by the service
    for(const formFieldKey of Object.keys(formVals)) {
        this.calculationService[formFieldKey] = formVals[formFieldKey]
    }
    this.calculationService.calculate();
}
/* Form C - Summary */
onFormChange() {
    const formVals = this.summaryForm.getRawValue();
    // I won't break this down as it doesn't have any calcuated values
    // however, it does show allCosts which is updated by the calculation service
    for (const formFieldKey of Object.keys(formVals)) {
        this.calculationService[formFieldKey] = formVals[formFieldKey]
    }
    this.calculationService.calculate();
}

/* Calculation Service */
calculate() {
    // Various calculations occcur here
    // All calcuations use the values of the service...not the individual forms
    // one of the values that is modified here is payment
    const loanPayment = ...; // math here to get the loanPayment
    const allCosts = ...; // this is the tricky part. I;m summing all of the subtotals
    this.bankForm.patchValues({
        loanPayment: calculatedLoanPayment // the other tricky part.  loanPayment affects the subtotal which has already been used above
    }, {emitEvent: false});
    this.summaryForm.patchValues({
        allCosts: calculatedAllCosts;
    });
}

person Wayne F. Kaskie    schedule 26.06.2019    source источник
comment
Не видя вашего кода, никто не сможет вам помочь.   -  person Adrian Brand    schedule 26.06.2019
comment
Ни одна служба никогда не должна знать о форме, чтобы исправлять значение формы.   -  person Adrian Brand    schedule 26.06.2019
comment
можешь добавить код, чтобы мы могли помочь?   -  person CruelEngine    schedule 26.06.2019
comment
абстрактно, я постараюсь, чтобы служба возвращала не только данные, которые должны быть изменены в A, также данные в B и C, и сделать несколько setValue, используя {emitEvent: false} с каждым из данных   -  person Eliseo    schedule 26.06.2019
comment
@AdrianBrand, я упоминал, что я новичок в реактивных формах. Как мне работать с данными в реактивной форме, если служба не должна исправлять форму? Мне нужно было использовать сервис, потому что у меня есть несколько форм, которые должны обмениваться данными друг с другом. Мой вопрос, по сути, заключается в том, как лучше всего это сделать?   -  person Wayne F. Kaskie    schedule 28.06.2019
comment
@CruelEngine, код, который у меня есть, очень простой. Вышеупомянутые отрывки - это все, что делается в формах. Функция расчета в сервисе - единственная, которая имеет дело с формами. Я только опустил детали расчетов. Те работают, как ожидалось.   -  person Wayne F. Kaskie    schedule 28.06.2019


Ответы (1)


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

Новый рабочий процесс: * Форма A изменяется - запускает службу вычислений * Служба Calc пересчитывает и выдает изменения * Форма A, B и C отвечает, сравнивая старые значения с новыми - Случай A: Форма A изменяется службой calc: она выдает изменение, которое запускает calc снова ~ Calc пересчитывает и выдает изменение ~ Формы A, B и C снова отвечают, но теперь нет никаких изменений. (это код, который мне кажется "бесполезным" ... или "лишним". ~ Конец - Случай B: никакие формы не меняются: ~ Конец

Это работает только потому, что в расчетах нет циклических ссылок. И это нормально, потому что ни одна электронная таблица не позволит этого.

person Wayne F. Kaskie    schedule 30.07.2019