首页 文章

Angular 2 / PrimeNG - 表达式在检查后发生了变化 . 在最后一个无效的表单控件上绑定NgModel

提问于
浏览
1

我有一个问题,当我的表单中的最后一个元素有一个绑定到它的值时,错误“表达式在检查后已经改变” . 被扔了 .

我将在序言中说这是基于Angular 2网站示例 - https://angular.io/docs/ts/latest/cookbook/dynamic-form.html#!#top

我的应用程序的工作方式首先是基于模型在我的表单组件中构建一个带有控件的动态表单 .

我的表单组件html循环模型中的问题,就像这样

<form *ngIf="showForm" [formGroup]="formGroup">
    <!-- questions-->
    <div *ngIf="questions.length > 0">
        <div *ngFor="let question of questions">
            <question [question]="question" [formGroup]="formGroup"></question>
        </div>
    </div>
    <button pButton type="submit" label="Submit" icon="fa-check-circle-o" iconPos="left"
            [disabled]="!formGroup.valid" (click)="submitFinalForm()"></button>
</form>

下面是问题组件html,它使用从表单组件传入的数据通过ngSwitch显示某些类型的问题

<label [attr.for]="question.field">
    {{ question.question }}
</label>
<div [ngSwitch]="question.type">
    <!-- Radio / Checkbox -->
    <radio-checkbox-question *ngSwitchCase="1" [formGroup]="formGroup" [question]="question"></radio-checkbox-question>
</div>

最后这里是radio-checkbox-question组件

<div *ngIf="showQuestion" [formGroup]="formGroup">
    <!-- Radio -->
    <div *ngIf="model.radiocheckbox == 'radio'">
        <div *ngFor="let label of model.labels; let i = index;">
             <p-radioButton name="{{model.field}}"
                            value="{{i}}"
                            label="{{label}}"
                            formControlName="{{model.field}}"
                            [(ngModel)]="questionAnswerRadio"></p-radioButton>
        </div>
    </div>
</div>

这是实际的组件TS

import { Component, Input, OnInit }         from "@angular/core";
import { FormGroup }                        from "@angular/forms";

import { RadioCheckboxQuestion }            from "../Questions/radio.checkbox.question.model";

@Component({
    selector: "radio-checkbox-question",
    templateUrl: "radio.checkbox.component.html"
})
export class RadioCheckboxComponent implements OnInit {

    @Input() question: any;
    @Input() formGroup: FormGroup;

    model: RadioCheckboxQuestion = new RadioCheckboxQuestion();
    showQuestion: boolean = false;

    questionAnswerRadio: string = "";

    ngOnInit(): void {
        // question essential properties
        if (this.question.hasOwnProperty("field") && this.question["field"] &&
            this.question.hasOwnProperty("labels") && this.question["labels"]) {
            this.model.field = this.question["field"];
            this.model.labels = this.question["labels"];

            // assume always radio for debugging
            this.model.radiocheckbox = "radio";

            // set existing answer
            if (this.question.hasOwnProperty("QuestionAnswer") && this.question["QuestionAnswer"]) {
                if (this.model.radiocheckbox == "radio") {
                    this.questionAnswerRadio = this.question["QuestionAnswer"];
                }
            }

            this.showQuestion = true;
        }
    }
}

我也看到了许多SO问题,如下面的Angular 2 dynamic forms example with ngmodel results in "expression has changed after it was checked",基本上说[[ngModel]]不应该与动态表单一起使用,但是primeNG文档说组件可以使用模型驱动的表单,并且是设置答案的唯一方法(我知道)是[(ngModel)] . 我相信这里可能会发生的事情是因为我将formGroup中唯一的问题设置为一个值,使得formGroup在更改检测之间变得有效并导致错误

Error in ./FormComponent class FormComponent - inline template:17:48 caused by: Expression has changed after it was checked. Previous value: 'false'. Current value: 'true'.

2 回答

  • 1

    从您的模板看起来您正在使用模型驱动器(formControlName)和模板驱动(ngModel) .

    <p-radioButton name="{{model.field}}"
                                value="{{i}}"
                                label="{{label}}"
                                formControlName="{{model.field}}"
                                [(ngModel)]="questionAnswerRadio"></p-
       <radioButton>
    

    请选择一种方式,然后重试 . 我建议你删除[(ngModel)]

  • 0

    我发现让变更检测对我的多嵌套组件和primeNG感到满意的唯一方法是手动实现完全变化检测 . 这基本上意味着在每个组件中我必须添加如下内容

    import ChangeDetectorRef
    
    constructor(private change: ChangeDetectorRef)
    {}
    
    ngOnInit() {
    
        // code here that inits everything
        this.change.markForCheck();
    }
    

    除此之外的任何事情都会导致更改检测错误以不同且独特的方式在使用primeNG的组件中弹出 .

相关问题