Angular2响应式表单和行为主体(BehaviorSubject)

4

我刚开始学习Angular,不知道如何通过异步调用更新响应式表单。

我有一个基于对象模型的响应式表单。表单中的任何更改都会触发一个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将接收到的问卷对象传递给父组件,在那里重新构建表单。


你应该使用 StackBlitz 或 Plunker 来展示你尝试做的事情,这样别人才能帮助你。 - Nitishkumar Singh
@NitishkumarSingh,我道歉了,这是代码。 - aygestan
@TheHeadRush 抱歉,已经更新了代码。 - aygestan
1
取消点踩。你需要手动更改检测。注入 ChangeDetectorRef 并在需要检测更改时调用 detectChanges - The Head Rush
1个回答

0

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

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

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

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

在 Angular 文档中找到:

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


抱歉,原来的问题不够明确,我已经包含了代码。 - aygestan
@aygestan 哦,是啊,这不再是一个新手问题了。明智的人决定不回答模糊的问题,避免因无关答案而被踩。 - Kyle Burkett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接