You can use formControlName
only on directives which implement ControlValueAccessor
.
Implement the interface
So, in order to do what you want, you have to create a component which implements ControlValueAccessor
, which means implementing the following three functions:
writeValue
(tells Angular how to write value from model into view)
registerOnChange
(registers a handler function that is called when the view changes)
registerOnTouched
(registers a handler to be called when the component receives a touch event, useful for knowing if the component has been focused).
Register a provider
Then, you have to tell Angular that this directive is a ControlValueAccessor
(interface is not gonna cut it since it is stripped from the code when TypeScript is compiled to JavaScript). You do this by registering a provider.
The provider should provide NG_VALUE_ACCESSOR
and use an existing value. You'll also need a forwardRef
here. Note that NG_VALUE_ACCESSOR
should be a multi provider.
For example, if your custom directive is named MyControlComponent, you should add something along the following lines inside the object passed to @Component
decorator:
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: forwardRef(() => MyControlComponent),
}
]
Usage
Your component is ready to be used. With template-driven forms, ngModel
binding will now work properly.
With reactive forms, you can now properly use formControlName
and the form control will behave as expected.
Resources
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…