Reputation: 28368
Demo: https://plnkr.co/edit/cMu3lI3PkxHRErJE3T93?p=preview
I've got a few components which all seem to have the same problem, and that is that I can't set a default value for ngModel
or formControlName
when using ControlValueAccessor
.
For example in the demo we have a select which provides better UX and visuals but in the ngOnInit
I can't set the model to be the first item in the provided options if the select has a required
input set to true
.
If true
, the select will always have a value. However now it only works after you actually clicked on an option.
One "solution" would be to always set the value in the parent of where it is being used. But that would require a lot of unnecessary code and I don't want to have to do that. Especially since setting a default value shouldn't be a problem.
So here's a short snippet of what we're working with:
private _model: any;
set model(val) {
this._model = val;
}
get model() {
return this._model;
}
propagateChange = (_: any) => {};
registerOnChange(fn: () => any) {
this.propagateChange = fn;
}
registerOnTouched() {}
writeValue(value: any) {
if (value !== undefined) {
this.model = value;
this.cd.markForCheck();
}
}
ngOnInit() {
if (!this.model && this.required) {
this.model = this.options[0];
}
else if (!this.required) {
this.model = null;
}
this.propagateChange(this.model);
}
As you can see in the demo, the setting of the model in ngOnInit
isn't working.
Why is this?
Upvotes: 2
Views: 1355
Reputation: 214295
When you call this.propagateChange(this.model);
this function has not registered yet.
So i know two workarounds
1) Update model after propagateChange
was assigned
export const NOOP: any = () => {};
...
propagateChange = NOOP;
registerOnChange(fn: () => any) {
this.propagateChange = fn;
if(this.required) {
fn(this.model);
}
}
writeValue(value: any) {
if (value !== undefined && this.propagateChange !== NOOP) {
this.model = value;
this.cd.markForCheck();
}
}
2) Use ngModelChange
event
@Output() ngModelChange = new EventEmitter();
this.ngModelChange.emit(this.model);
Upvotes: 3