I have a custom form control which implements ControlValueAccessor to handle [(formControl)]="..."
and [(ngModel)]="..."
.
@Component({
selector: 'app-foo',
templateUrl: './foo.component.html',
styleUrls: ['./foo.component.css'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => FooComponent),
multi: true,
},
],
})
export class FooComponent implements ControlValueAccessor, OnInit, AfterContentInit, OnInit, OnChanges, DoCheck, AfterContentChecked, AfterViewInit, AfterViewChecked {
constructor() { }
ngOnChanges() {
console.log('ngOnChanges', this.value);
}
ngOnInit() {
console.log('ngOnInit', this.value);
}
ngDoCheck() {
console.log('ngDoCheck', this.value);
}
ngAfterContentInit() : void {
console.log('ngAfterContentInit', this.value);
}
ngAfterContentChecked() : void {
console.log('ngAfterContentChecked', this.value);
}
ngAfterViewInit() : void {
console.log('ngAfterViewInit', this.value);
}
ngAfterViewChecked() : void {
console.log('ngAfterViewChecked', this.value);
}
/**
* Write a new value to the element.
*/
public writeValue(value : any) : void { // tslint:disable-line:no-any
this._value = value;
console.log('writeValue', this.value);
}
...
I use this component like this:
<app-foo [ngModel]="true"></app-foo>
I assumed the value should be defined at least in ngAfterContentInit() but it is always undefined or null. At least in the first run. Here are my console logs:
ngOnInit undefined
ngDoCheck undefined
writeValue null
ngAfterContentInit null
ngAfterContentChecked null
ngAfterViewInit null
ngAfterViewChecked null
---
writeValue true
ngDoCheck true
ngAfterContentChecked true
ngAfterViewChecked true
Why is value always undefined/null and is there a way to change that?
You will need to implement ControlValueAccessor in order to make it work :
The
writeValue
function will be executed when the input value ofngModel
change. You will also have to implementregisterOnTouch
andregisterOnChange
.Have a look at this alligator.io article for a more information.