简体   繁体   English

Angular2 Reactive Forms和BehaviorSubject

[英]Angular2 Reactive Forms and BehaviorSubject

I am new to Angular and cannot figure out updating reactive forms with async calls. 我是Angular的新手,无法确定使用异步调用更新反应式表单。

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. 表单中的任何更改都会触发HTTP请求,该请求可能会将对象的更新版本作为响应发回。 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. 我使用BehaviorSubject实现了类似的东西(那些对象的列表),但不知道如何使用表单。

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. 我在这里遇到的问题是valueChanges监听器将新问卷识别为更改,并且我的应用程序陷入无限循环的HTTP请求。

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. 我最终最终使用EventEmitter将收到的问卷调查对象传递给父组件,在那里我重建了表单。

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: 在Angular文档中找到:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM