【问题标题】:Angular2 Reactive Forms and BehaviorSubjectAngular2 响应式表单和 BehaviorSubject
【发布时间】:2019-01-23 16:55:16
【问题描述】:

我是 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 来展示你试图做什么。所以其他人可以帮助你
  • @NitishkumarSingh 抱歉,这是代码
  • @TheHeadRush 抱歉,已更新代码
  • 已撤回反对票。手动更改检测是您所需要的。当您希望检测到更改时,注入ChangeDetectorRef 并调用detectChanges

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


【解决方案1】:

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

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

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

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

在此处的 Angular 文档中找到:

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

【讨论】:

  • 抱歉,问题本来就含糊不清,我把代码加进去了。
  • @aygestan 哦,是的,不再是菜鸟问题。决定不回答模糊问题的聪明人会避免对不相关的答案投反对票
猜你喜欢
  • 2018-05-13
  • 2017-05-04
  • 1970-01-01
  • 2017-12-30
  • 1970-01-01
  • 1970-01-01
  • 2020-05-19
  • 2018-05-05
  • 2017-04-15
相关资源
最近更新 更多