I am new to Angular and cannot figure out updating reactive forms with async calls.
I have a reactive form based on an object model. Any change in the form triggers an HTTP request that might send back an updated version of the object as a response. I need to update the form accordingly.
I implemented a similar thing (list of those objects) with BehaviorSubject, but not sure how to do it with a form.
EDIT: Sorry for not including code. It is rather messy, so here is a summary.
Here is what I have right now:
export class EditQuestionnaire implements OnInit {
questionnaireForm: FormGroup;
questionnaire: Observable<Questionnaire>;
// constructor with its dependencies omitted
ngOnInit() {
this.questionnaireForm = this.fb.group({
'id': [''],
'submitted': [false],
'questions': this.fb.array(
[]
),
});
this.questionnaire = this.questionnaireService.getQuestionnaireGeneral(); // This is an observable of a BehaviorSubject that gets updated in a service with every call to getQuestionnaire
this.questionnaireService
.getQuestionnaire(this.questionnaire.id)
.subscribe(questionnaire => {
this.questionnaireForm = this.loadQuestionnaire(questionnaire); // loads the questionnaire into the form
});
}
...
}
What I also have is a child component denoting a question in the questionnaire. Here I detect the changes:
export class QuestionComponent implements OnInit {
@Input() questionForm: FormGroup;
@Input() questionnaireId: string;
// constructor and dependencies omitted
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(); // no need to rebuild here
}
saveAnswer(questionId: string, answerId: string) {
this.questionnaireService.updateAnswer(questionnaireId, questionId, answerId).subscribe(questionnaire => { /* trigger the form to rebuild */ })
}
}
Answers to certain questions might trigger follow-up questions, so a whole new questionnaire is sent back from the back end. The problem I am encountering here is that the valueChanges listeners identify the new questionnaire as a change, and my application gets stuck in an infinite loop of HTTP requests.
Any ideas how to work around this problem?
UPDATE:
I eventually ended up using an EventEmitter to pass the received questionnaire object to the parent component, where I rebuild the form.
I assume you trigger the request from a service through the component. To update a reactive form object from your component, you can assign it directly. For instance, if you declare your reactive form like this:
this.form = new FormGroup({
name: new FormControl()
})
You can update the name simply like this:
let name = "Kyle";
this.form.controls.name.value = name;
Found in the Angular documentation here:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.