ControlValueAccessor中的AngularX ngOnChange

时间:2017-03-16 03:26:42

标签: angular reactive-programming

我有控件从json架构构建表单并将值传播为对象。 这个组件是在设置json模式的其他控件内部,问题是当我更改输入值jsonSchema时我需要传播新值(因为表单在jsonSchema值更改期间重建)但是我收到错误<登记/> Expression has changed after it was checked. Previous value: 'true'. Current value: 'false'.这是因为在乞讨表格上是有效的,因为没有设置任何字段,但在设置后,带有必填字段形式的jsonSchema变为无效。

@Component({
  selector: 'name',
  templateUrl: './json-schema-form.component.html',
  styleUrls: ['./json-schema-form.component.css'],
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: JsonSchemaFormComponent,
    multi: true
  }, {
    provide: NG_VALIDATORS,
    useExisting: JsonSchemaFormComponent,
    multi: true
  }]
})
export class JsonSchemaFormComponent implements OnChanges, ControlValueAccessor, Validator {
  private propagateChange: Function = function (change) { };
  private propagateTouch: Function = function () { };
  @Input() jsonSchema: any;
  @Input() defaultValues: any;
  registerForm: FormGroup = new FormGroup({});
  customProperties: any[];
  constructor() { }

  validate(c: AbstractControl): { [key: string]: any; } {
    return this.registerForm.valid ? null : { "json-form": true };
  }

  writeValue(obj: any): void {

  }

  public registerOnChange(fn) {
    this.propagateChange = fn;
  }

  public registerOnTouched(fn) {
    this.propagateTouch = fn;
  }

  ngOnInit() {
  }

  ngOnChanges(changes: SimpleChanges) {
    this.setupForm();
  }

  private setupForm() {
    var formData = {};
    this.registerForm.addControl("test", new FormControl("", [Validators.required]));
    this.propagateChange(this.registerForm.value);
  }
}

临时修复是我延迟传播事件。但我不喜欢任何延误的想法..

this.controlChanged
      .debounceTime(5)
      .subscribe(() => {
        console.log("JsonSchemaFormComponent", this.registerForm);
        this.propagateChange(this.registerForm.value);
      });
    this.registerForm.valueChanges.subscribe(() => {
      this.controlChanged.next();
    });

我已经复制了这个例子。打开开发人员工具栏控制台,然后尝试在输入中设置任何数字

https://plnkr.co/edit/ZmYBiH6kciXqQXp2f3KU

1 个答案:

答案 0 :(得分:2)

正如我在评论中提到的那样,因为角度是建立在单向数据流上的,你必须通过setTimeout或以这种方式触发下一个滴答:

const resolvedPromise = Promise.resolve(null);
...
resolvedPromise.then(() => {
   this.propagateChange(this.registerForm.value);
});

<强> Modified Plunker