How to set values of angular custom input components (control value accessors) from parent?

Viewed 1758

We have the ability to set values (in case if needed) for native input elements such as checkboxes, text input etc..

It will be like this :

<input type="text" [value]="customValue">

In this way we can bind custom values to the native input elements.

How can I achieve similar result with a custom input element implemented with control value accessor?

For example consider this custom Input component:


@Component({
  selector: 'child-custom-input',
  templateUrl: './child-custom-input.component.html',
  styleUrls: [],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => ChildCustomInputComponent),
      multi: true,
    },
  ],
})
export class ChildCustomInputComponent implements ControlValueAccessor {
  _value: boolean;

  onChanged: any = () => {};
  onTouched: any = () => {};

  constructor() {}

  writeValue(value: any) {
    this._value = value;
  }

  registerOnChange(fn: any): void {
    this.onChanged = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  setValue(value) {
    this._value = value;
    this.onChanged(value);
    this.check.emit(value);
  }

Following is from the parent component:

// parent-component.html

<child-custom-input [value]="customInputValue"> </child-custom-input>

How can I achieve such a result?

Like setting a default/ initial value from the parent component to the custom child input component.

// child-custom-input.component.html

<input type="text" placeholder="Input something..." (input)="setValue($event.target.value)">

Or could be something like a checkbox. The only thing required is to set value from the parent component to this custom child input component.

// child-custom-input.component.html

<input type="checkbox" (input)="setValue($event.target.checked)">
1 Answers

In order to do so, you need to also define an @Input() value: any property and the appropriate getter and setter in your ChildCustomInputComponent.

export class ChildCustomInputComponent implements ControlValueAccessor {
.
.
.

  //The internal data model
  private innerValue: any = '';

  //get accessor
  @Input()
  get value(): any {
    return this.innerValue;
  }

  //set accessor including call the onchange callback
  set value(v: any) {
    if (v !== this.innerValue) {
      this.innerValue = v;
      this.onChangeCallback(v);
    }
  }

}

That way you should be able to use the ChildCustomInputComponent and define their value property from any parent component like this:

<custom-input name="myCustomComponent" [value]="'Any value here'"></custom-input>

For further clarification please check the following working example: https://plnkr.co/edit/zNOYwrLsszY54DDL

Related