角度:ExpressionChangedAfterItHasBeenCheckedError子组件和FormControl

时间:2018-11-15 17:40:28

标签: angular

我已经看过,阅读并尝试过许多有关此主题的问题,答案和博客。我了解为什么我的代码中会发生这种情况,只是不知道如何解决。

(简化真实代码;如果我犯了错误或忘记了重要的事情,请在评论中让我知道)

我有一个带有输入的上级组件A和一个下级组件B。

<form [formgroup]="modalForm">
   <input type="text" formControlName="text"></input>
   <componentB 
    [formControl]="modalForm.controls['componentB'] 
    [firstProperty]="foo" 
    [secondProperty]="bar">
   </componentB>
</form>

ComponentB也有一个输入和一个自定义消息组件:

<div>
   <input type="text" [formControl]="formControl"></input>
   <message
    [message]="firstProperty" 
    [secondMessage]="secondProperty">
   </message>
</div>

ComponentA:

export class ComponentA implements OnInit{

  public foo: string;
  public bar: string;
  public modalFrom: FormGroup;

  public constructor(private componentBValidatorFactory: ComponentBValidatorFactory){}

  public ngOnInit(): void {
    this.modalForm = new FormGroup({
     text: new FormControl(null),
     componentB: new FormControl(null, {
        validators: Validators.required,
        asyncValidatiors: [this.componentBValidatorFactory.asyncValidatorFn()],
        updateOn: 'blur'
        })
    });
  this.modalForm.controls['text'].valueChanges(subscribe( () => this.textChanged());
  this.modalForm.controls['componentB'].valueChanges(subscribe( () => this.componentBChanged());
  }

  private textChanged(): void {
  this.foo = this.modalForm.controls['text'].value;
  }

  private componentBChanged(): void {
  this.bar = this.modalForm.controls['componentB'].value + 'somestring';
  }
}

ComponentB(简体):

export class ComponentB{

@Input()
public formControl: FormControl;

@Input()
public firstProperty: string;

@Input()
public secondProperty: string;

}

问题(据我了解): text发生更改(用户输入)时,它将使用值更新foo。这意味着ComponentB发生了变化,因此ComponentB的valueChanges被触发。 ComponentBChanged被触发并更新bar。 当text再次更改时,bar再次更改,但是由于它与第二次处理foo时的先前值不同,我得到了众所周知的ExpressionChangedAfterItHasBeenCheckedError(值已正确处理)。 据我了解: ComponentB已更新(foo),这将触发同一组件(bar)绑定的另一项更改。这并不能使Angular开心。 直接将输入放入ComponentB(也有一个输入字段)可以很好地工作,它可以正确更新bar,而不会出现问题。

我该怎么做才能无问题地更新bar?我无法在代码中的bar中更新textChanged,因为如果直接操纵ComponentB,更新也应该发生。

1 个答案:

答案 0 :(得分:0)

不是将FormControl传递给child Use,而是将foo和bar属性分配为null

formControlDirective

  

此伪指令接受现有的FormGroup实例。然后它将   使用此FormGroup实例来匹配任何子FormControl,FormGroup,   和FormArray实例添加到子FormControlName,FormGroupName和   FormArrayName指令。

Parent.component.html

@RequestMapping(path = "/handleResponse", method = RequestMethod.GET)
public String handleResponse(@RequestParam(name = "token")
final String token, @RequestParam(name = "PayerID")
final String payerId)

app-component-a.ts

<form [formGroup]="form">
  <label >Text</label>
  <input formControlName="text">
  <app-component-a 
  [firstProperty]="foo" 
    [secondProperty]="bar"
  ></app-component-a>
</form>

示例:https://stackblitz.com/edit/angular-65nmvr