角形变化检测

时间:2018-09-13 11:24:26

标签: angular ionic-framework rxjs ionic3 angular-forms

我正在使用Angular表单,我想使用它们的内置更改检测来在我的应用程序中实现功能。用户单击按钮时,只有在对表单进行了任何更改的情况下,他/她才应该看到对话框。

我有changesMade变量:

private changesMade: boolean;

这是我的TS格式的代码:

this.carForm = new FormGroup({
        name: new FormControl('', [
            Validators.required,
            Validators.pattern('[a-zA-Z ]*'),
            Validators.minLength(1),
            Validators.maxLength(10)
        ])});

这是我的以下形式的HTML代码:

<form [formGroup]="carForm">
        <ion-item>
          <ion-label  stacked>car name</ion-label>
          <ion-input type="text" [(ngModel)]="carname" formControlName="name"></ion-input>
        </ion-item>
</form>

这是我的模拟(现在)服务调用,在我设置了与输入绑定的carname值后,我订阅了表单更改

setTimeout(()=>{
  this.carname = "BMW";
  this.carForm.valueChanges.subscribe(val => {
  this.changesMade = true;
    });
}, 44)

这里的问题是,即使我没有触摸表格,this.changesMade也会设置为true。

注意:如果我将代码的订阅部分移动到ngAfterViewInit中,即使我没有推送输入,它仍然会将changesMade设置为true:

  ngOnInit(){
    //simulated server call
    setTimeout(()=>{
      this.carname = "BMW";

    }, 44)
  }
      ngAfterViewInit(){
this.carForm.valueChanges.subscribe(val => {
      this.changesMade = true;
        });
    }

我创建了一个STACKBLITZ来说明问题。仅当我实际触摸过UI中的输入时,如何才能使其执行this.changesMade = true;

2 个答案:

答案 0 :(得分:1)

这里的问题是您正在混合反应形式和ngModel。由于您已在模板中使用ngModel,并在组件中设置了this.carName = 'BMW',因此会触发更改检测,并且formGroup得到更新,并且您的changesMade标志变为true。删除ngModel并使用反应性表单API:https://angular.io/guide/reactive-forms#reactive-forms-api获得表单值。

我已经更新了STACKBLITZ:https://stackblitz.com/edit/ionic-qkjeu6?file=pages%2Fhome%2Fhome.ts

答案 1 :(得分:-1)

因此,通过将预订放在调用堆栈的末尾(使用setTimeout(0)),一切似乎都按预期工作:

//simulated server call
setTimeout(()=>{
  this.carname = "BMW";
  setTimeout(function(){
  this.carForm.valueChanges.subscribe(val => {
  this.changesMade = true;
    });
  }.bind(this), 0)

}, 44)

这是STACKBLITZ,表明它有效。

更新

由于将响应式表单与ngModel一起使用deprecated in Angular 6+,因此在类似的用例中,最好用模板驱动的表单来替换响应式。