Search code examples
angularangular6angular-reactive-forms

ControlValueAccessor not working when component inserted dynamically


InputFieldComponent component developed using implements ControlValueAccessor

constructor(public cd: ChangeDetectorRef) {

}

onTouchedCallback = () => { };
onChangeCallback: any = () => { };

// register a handler that should be fired when something in the view has changed
registerOnChange(fn: any): void {
  this.onChangeCallback = fn;
}

// registers a handler specifically for when a control receives a touch event.
registerOnTouched(fn: any): void {
  this.onTouchedCallback = fn;
}

// writes new values from the form model into the view or any DOM property
writeValue(value: string): void {
  if (value !== this.innerValue) {
    this.innerValue = value;
  }
}

// textbox input change
onChange(event: any): void {
  this.onChangeCallback(event.target.value);
}

added dynamically like this.

const componentFactory = this.componentFactoryResolver.resolveComponentFactory(InputFieldComponent);
const newComponent = container.createComponent(componentFactory);

Set up

form.addControl("firstname",
                new FormControl("Some TEXT ", Validators.required));

newComponent.instance.formControlName = "firstname"

trying to fire writeValue by writing below line :

newComponent.instance.cd.detectChanges();

but no luck, how do to solve this problem? i want to see "Some TEXT" in textbox value.

normally if i used this component html, it is working expected.

here stackblitz link for what i tried : -

https://stackblitz.com/edit/angular-custom-input-init-value-d34jls


Solution

  • You're mixing Template Driven Forms (Using ngModel) and Reactive Forms, which is deprecated in your Angular version and will be removed in a future version of Angular.

    What I would suggest, although it feels hacky, is to input the FormControl to the dynamic ControlValueAccessor component you just created: https://stackblitz.com/edit/angular-custom-input-init-value-fuxwks

    I highly suggest you re-think of a design for whatever you're trying to achieve.

    P.S. use <ng-template></ng-template> instead of <template></template>. This is encouraged since Angular 4.