Динамически выполнять расчет после того, как форма становится действительной в Angular

Я использую Reactive Forms и пытаюсь динамически выполнять математические вычисления, как только formGroup становится действительным.

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

Я пытался использовать ngIf, чтобы проверить, действительна ли formGroup, затем вызвать функцию, передать ей номер индекса (для захвата необходимых элементов управления формой), а затем выполнить расчет:

HTML

<div>
   Sum: 
    <ng-container *ngIf = "roundInputs.get(roundCount + '')?.valid ? calculateHandicapBtnClick(roundCount) : null">
       <span *ngFor = "let total of roundTotal; let sumCount = index">
          <span *ngIf = "roundCount === sumCount">
            {{total}}
          </span>
            {{total}}
          </span>
     </ng-container>
</div>

ТС

  calculateHandicapBtnClick(roundNumber: number) {
    this.roundTotal = [];
    let tempArray = [];
    let eighteeenHoleScore = this.roundInputs.controls[roundNumber].get('eighteenHoleScore')?.value;
    let nineHoleScore = this.roundInputs.controls[roundNumber].get('nineHoleScore')?.value;
    let total = eighteeenHoleScore + nineHoleScore
    this.roundTotal.push(total);
    // this.roundTotal.splice(roundNumber, 0, total)
    // this.roundTotal.push(eighteeenHoleScore + nineHoleScore)

    // this.roundInputs.controls.forEach((control) => {
    //   eighteeenHoleScore = control.get('eighteenHoleScore')?.value
    //   nineHoleScore = control.get('nineHoleScore')?.value
    //   this.roundTotal.push(eighteeenHoleScore + nineHoleScore)

    // })
  }

Вот что у меня есть для настройки formGroups вместе с тем, как работает addRound():

get roundInputs(): FormArray{
    return <FormArray>this.roundForm.get('roundInputs')
  }

  ngOnInit(): void {
    this.roundForm = this.fb.group({
      roundInputs: this.fb.array([ this.buildRoundForm() ])
    })
  };

addRound() {
   this.roundInputs.push(this.buildRoundForm())
  }

Кажется, я не могу собрать общую сумму и отобразить ее на странице. В консоли я вижу, что мои журналы удваиваются после того, как форма становится действительной, и когда я выхожу из ввода, а затем щелкаю в другом месте на странице. Из того, что я прочитал, мне, вероятно, не следует вызывать функцию в HTML, так как обнаружение изменений приведет к ее запуску несколько раз (где, как если бы я привязал ее к btn, у меня не так много проблем) . Вы также можете видеть, что я пробовал различные другие вещи, которые закомментированы, такие как цикл по всем элементам управления формы или попытка склеить и поместить итог в определенную позицию в массиве (я использую массив значений, чтобы затем перебрать и заполните эти значения на странице)

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

Вот скриншот приложения и то, что я пытаюсь сделать. Вы можете игнорировать кнопку «Рассчитать гандикап», поскольку я пытаюсь поэтапно отказаться от нее и заменить ее приведенным выше сценарием.

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

Yogi 31.03.2023 03:59

Группа форм содержит свойство для прослушивания изменений своего статуса, поэтому, возможно, вы можете его использовать, здесь ссылка на документ: angular.io/api/forms/AbstractControl#statusChanges

Yogi 31.03.2023 04:03

@Yogi Я добавил в описание код того, как настраиваются группы форм, а также то, как работает addRound. Я просмотрел изменения статуса, которые, я думаю, решат мою проблему, однако как бы вы не реализовали их для конкретной группы форм? Так, например, скажем, у меня есть 2 раунда, и второй раунд действителен, а первый раунд — нет. Прямо сейчас у меня есть ниже в ngOnInit, и он срабатывает только в том случае, если все раунды/formGroups действительны this.roundInputs.statusChanges.pipe( filter(status => status === 'VALID') ) .subscribe(() => { console.info("working") })

Eric Petela 31.03.2023 22:33

Посмотрите ответ @Eliseo, он охватывает различные подходы к достижению того, чего вы хотите.

Yogi 01.04.2023 00:09
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
4
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

// let's say you subscribe to it inside ngOnInit

this.roundInputs.statusChanges
  .pipe(
    filter(status => status === 'VALID'),
    takeUntil(this.untilDestroyed$) // just to be sure, unsubscribe on destroy
  )
  .subscribe(() => {
    this.calculateHandicapBtnClick(roundNumber) // provide the value
    //call your function
  });
Ответ принят как подходящий

вы можете использовать

<ng-container *ngIf = "roundInputs.get(roundCount + '')?.valid  &&
                        calculateHandicapBtnClick(roundCount)">
...
</ng-container>

всегда вы возвращаете true в своей функции

calculateHandicapBtnClick(roundCount){
  ....
  return true;
}

Но это лучше, поскольку Йоги предполагают, что лучше использовать statusChanges. Я предполагаю, что у вас есть функция, которая возвращает formGroup и геттер для вашего массива.

get array()
{
    return this.form.get('myArrayHoles') as FormArray
}
setFormGroup()
{
   const formGroup=new FormGroup({
       eighteenHoleScore:new FormControl(0),
       nineHoleScore:new FormControl(0)
   });
   const newFormIndex = this.array.length - 1;
   formGroup.statusChange.pipe(filter(res => res === 'VALID')).subscribe(res=>{
       this.calculateHandicapBtnClick(newFormIndex) //<--see how you pas the "index"
   })
   return formGroup;
}

Ну, если вы не хотите подписываться и отписываться, вы можете иметь массив «наблюдаемых»

observablesTotal$:Observable<number>[]=[] 

И заполните массив при создании формы

setFormGroup()
{
   const formGroup=new FormGroup({
       eighteenHoleScore:new FormControl(0),
       nineHoleScore:new FormControl(0)
   });
   const newFormIndex = this.array.length - 1;
   observablesTotal$[newFormIndex] = formGroup.statusChange.pipe(
             filter(res => res === 'VALID'),
             map(_=>this.calculateHandicapBtnClick(newFormIndex))
   )
   return formGroup;
}

Таким образом, вы можете использовать в своем .html

   SUM: {{observablesTotal$[index]|async}}

Большое спасибо за это! У меня работает statusChange, поэтому он сообщает мне, действительна ли моя конкретная группа форм или нет. Вы ссылаетесь на передачу индекса в calculateHandicapBtnClick, но поскольку эта функция находится вне цикла ngFor в HTML, я не уверен, как получить индекс и передать его. Я видел, что мог бы использовать @Input, чтобы захватить его, но, похоже, это не работает. Я не могу переместить функцию в цикл for, потому что тогда кнопка явно повторяется

Eric Petela 03.04.2023 03:11

Другие вопросы по теме