Я использую 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 или даже, возможно, пытался принудительно обнаружить изменения. Я действительно не нашел ничего, что работает, поэтому ищу какой-то вклад.
Вот скриншот приложения и то, что я пытаюсь сделать. Вы можете игнорировать кнопку «Рассчитать гандикап», поскольку я пытаюсь поэтапно отказаться от нее и заменить ее приведенным выше сценарием.
Группа форм содержит свойство для прослушивания изменений своего статуса, поэтому, возможно, вы можете его использовать, здесь ссылка на документ: angular.io/api/forms/AbstractControl#statusChanges
@Yogi Я добавил в описание код того, как настраиваются группы форм, а также то, как работает addRound. Я просмотрел изменения статуса, которые, я думаю, решат мою проблему, однако как бы вы не реализовали их для конкретной группы форм? Так, например, скажем, у меня есть 2 раунда, и второй раунд действителен, а первый раунд — нет. Прямо сейчас у меня есть ниже в ngOnInit, и он срабатывает только в том случае, если все раунды/formGroups действительны this.roundInputs.statusChanges.pipe( filter(status => status === 'VALID') ) .subscribe(() => { console.info("working") })
Посмотрите ответ @Eliseo, он охватывает различные подходы к достижению того, чего вы хотите.
Сделайте это в части 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, потому что тогда кнопка явно повторяется
Вы создаете группы форм для каждого круглого раздела, который виден на скриншоте? Вы хотите предпринять действие всякий раз, когда любой из них становится действительным? что делает слушатель добавления круглого клика?