Update: Link to Plunker
Running into a weird problem. I'm using Angular 2.4.1. When the component initially loads, the value setter runs and onChangeCallback correctly fires. However, I am console-logging onChangeCallback, and after it is initially set, it is being replaced with an anonymous function.
Here are the results of the console.log:
- function (_) { }
function (newValue) { dir.viewToModelUpdate(newValue); control.markAsDirty(); control.setValue(newValue, { emitModelToViewChange: false }); }
function (_) { }
The first happens on page load, immediately followed by 2. I'm assuming Angular is handling the token and implementing ControlValueAccessor correctly at this point. When I then make a change on the select element, onChangeCallback is being called as the anonymous function again without the ControlValueAccessor additions.
Any idea on how to fix this? It is only this form-control that I'm having this problem with.
import { Component, Input, Output, EventEmitter, forwardRef, ViewChild, ElementRef, Renderer, ChangeDetectorRef, OnChanges } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'select-resizable',
template:`
<select #mainSelectElement [(ngModel)]="value" (change)="updateSelected($event.target.value)" style="width: initial;">
<ng-content></ng-content>
</select>
<select class="usa-sr-only" aria-hidden="true" role="presentation" #hiddenSelectElement style="width: initial;">
<option>{{value}}</option>
</select>
`,
providers: [
{ provide: NG_VALUE_ACCESSOR, useClass: forwardRef(() => SelectResizableComponent), multi: true }
]
})
export class SelectResizableComponent implements ControlValueAccessor {
@ViewChild('hiddenSelectElement') hiddenSelectElement: ElementRef;
@ViewChild('mainSelectElement') mainSelectElement: ElementRef;
private _selected: any;
private onChangeCallback: (_: any) => void = (_: any) => {};
private onTouchedCallback: () => void = () => {};
get value(): any {
return this._selected;
}
set value(val: any) {
this._selected = val;
this.onChangeCallback(val);
console.log(this.onChangeCallback);
}
constructor(private renderer: Renderer, private ref: ChangeDetectorRef) {}
updateSelected(event) {
this.ref.detectChanges();
const width = (this.hiddenSelectElement.nativeElement.clientWidth * 1.02) + 'px';
this.renderer.setElementStyle(this.mainSelectElement.nativeElement, 'width', width);
}
writeValue(val: any) {
this.value = val;
}
registerOnChange(fn: any) {
this.onChangeCallback = fn;
}
registerOnTouched(fn: any) {
this.onTouchedCallback = fn;
}
}
SelectResizableComponentmore than once? The console.log could be running from a second use of the component. - Adam