As a newcomer to Angular, I am struggling with updating reactive forms after making asynchronous calls.
My specific challenge involves having a reactive form linked to an object model. Whenever there is a change in the form, it triggers an HTTP request that returns an updated version of the object as a response. I then need to update the form based on this new data.
In a previous instance, I successfully implemented a similar functionality (a list of objects) using BehaviorSubject. However, I'm unsure how to achieve the same outcome with a form.
To provide more context, here is a summarized version of my current code:
export class EditQuestionnaire implements OnInit {
questionnaireForm: FormGroup;
questionnaire: Observable<Questionnaire>;
// constructor and dependencies not shown
ngOnInit() {
this.questionnaireForm = this.fb.group({
'id': [''],
'submitted': [false],
'questions': this.fb.array(
[]
),
});
this.questionnaire = this.questionnaireService.getQuestionnaireGeneral();
this.questionnaireService
.getQuestionnaire(this.questionnaire.id)
.subscribe(questionnaire => {
this.questionnaireForm = this.loadQuestionnaire(questionnaire);
});
}
...
}
Additionally, I have a child component representing a question within the questionnaire structure where changes are detected:
export class QuestionComponent implements OnInit {
@Input() questionForm: FormGroup;
@Input() questionnaireId: string;
// constructor and dependencies not shown
get text() {
return this.questionForm.get('text') as FormControl;
}
get answers() {
return this.questionForm.get('answers') as FormArray;
}
get id() {
return this.questionForm.get('id') as FormControl;
}
get comment() {
return this.questionForm.get('comment') as FormControl;
}
ngOnInit() {
const questionId = this.id.value;
this.comment.valueChanges
.pipe(
debounce(() => interval(2000))
)
.subscribe(newValue => {
this.saveComment(questionId, newValue);
});
for (const answer of this.answers.controls) {
this.answers.valueChanges.subscribe(val => {
const answerId = answer.get('id').value;
this.saveAnswer(questionId, answer);
});
}
saveComment(questionId: string, comment: string) {
this.questionnaireService.updateComment(questionnaireId, questionId, comment).subscribe();
}
saveAnswer(questionId: string, answerId: string) {
this.questionnaireService.updateAnswer(questionnaireId, questionId, answerId).subscribe(questionnaire => { /* trigger the form to rebuild */ })
}
}
One key issue arises when answers to certain questions lead to follow-up questions, resulting in an entirely new questionnaire sent from the backend. The problem lies in the valueChanges listeners recognizing this new questionnaire as a change, causing my application to be stuck in an infinite loop of HTTP requests.
Anyone have suggestions on how to address this dilemma?
LATEST UPDATE:
Ultimately, I decided to utilize an EventEmitter to transmit the received questionnaire object to the parent component, where I can reconstruct the form accordingly.