Angular2反应形式和BehaviorSubject

时间:2018-08-16 16:55:01

标签: angular typescript angular-reactive-forms angular-forms angular-observable

我是Angular的新手,无法弄清楚使用异步调用更新反应式表单。

我有一个基于对象模型的反应形式。表单中的任何更改都会触发HTTP请求,该HTTP请求可能会发送回对象的更新版本作为响应。我需要相应地更新表格。

我用BehaviorSubject实现了类似的东西(这些对象的列表),但是不确定如何用表单来实现。

编辑:很抱歉,不包含代码。相当混乱,所以这里是一个摘要。

这是我现在拥有的:

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
            });
    }
    ...
}

我还有一个儿童成分,表示问卷中的一个问题。在这里,我检测到更改:

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 */ })
    }
}

某些问题的答案可能会引发后续问题,因此将从后端发回一份全新的调查表。我在这里遇到的问题是valueChanges侦听器将新调查表识别为更改,并且我的应用程序陷入了HTTP请求的无限循环中。

任何想法如何解决此问题?

更新:

最终我最终使用EventEmitter将接收到的调查表对象传递给父组件,然后在其中重建表单。

1 个答案:

答案 0 :(得分:0)

我假设您通过组件触发了来自服务的请求。要从组件更新反应式表单对象,可以直接分配它。例如,如果您这样声明反应式:

this.form = new FormGroup({
        name: new FormControl()
})

您可以像这样简单地更新名称:

let name = "Kyle";
this.form.controls.name.value = name;

在以下Angular文档中找到:

https://angular.io/api/forms/FormControl