You can find demo here in this stackblitz link
For your any custom-component if you need to use [(ngModel)] then you need to use your custom ControlValueAccessor base class.
Create one class called AbstractValueAccessor...
import { forwardRef } from "@angular/core";
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
const noop = () => {};
export abstract class AbstractValueAccessor implements ControlValueAccessor {
//The internal data model
private innerValue: any = "";
//Placeholders for the callbacks which are later provided
//by the Control Value Accessor
private onTouchedCallback: () => void = noop;
private onChangeCallback: (_: any) => void = noop;
//get accessor
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);
}
}
//Set touched on blur
onBlur() {
this.onTouchedCallback();
}
//From ControlValueAccessor interface
writeValue(value: any) {
if (value !== this.innerValue) {
this.innerValue = value;
}
}
//From ControlValueAccessor interface
registerOnChange(fn: any) {
this.onChangeCallback = fn;
}
//From ControlValueAccessor interface
registerOnTouched(fn: any) {
this.onTouchedCallback = fn;
}
}
export function MakeProvider(type: any) {
return {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => type),
multi: true,
};
}
Now, You need to use above class in you custom-component.
custom-component
import { Component, OnInit } from "@angular/core";
import {
AbstractValueAccessor,
MakeProvider,
} from "../app/abstract-value-accessor";
@Component({
selector: "app-custom-input",
templateUrl: "./custom-input.component.html",
styleUrls: ["./custom-input.component.css"],
providers: [MakeProvider(CustomInputComponent)],
})
export class CustomInputComponent
extends AbstractValueAccessor
implements OnInit
{
ngOnInit() {}
}
above, providers: [MakeProvider(CustomInputComponent)] this line we provide our custom value accessor to our component. Now , we are ready to use this component.
app-component.html
<app-custom-input [(ngModel)]="customValue"></app-custom-input>
app-component.ts
customValue = 'custom-value';