Reputation: 145
I have implemented Control Value Accessor in my application but when running the application I get the following error message:
ERROR TypeError: dir.valueAccessor.writeValue is not a function
at setUpControl (forms.js:2578)
at FormGroupDirective.addControl (forms.js:6318)
at FormControlName._setUpControl (forms.js:6969)
at FormControlName.ngOnChanges (forms.js:6892)
at checkAndUpdateDirectiveInline (core.js:24499)
at checkAndUpdateNodeInline (core.js:35163)
at checkAndUpdateNode (core.js:35102)
at debugCheckAndUpdateNode (core.js:36124)
at debugCheckDirectivesFn (core.js:36067)
at Object.eval [as updateDirectives] (AnnouncementInformationListComponent.html:82)
This is how I set it up:
AnnouncementInformationListComponent.html
<form [formGroup]="_form">
<div [formArrayName]="item.code">
<div *ngFor="let controlItem of _form.get(item.code).controls; let ctrlIndex = index"
class="form-row"
[formGroupName]="ctrlIndex">
<div [ngClass]="{'col-8': oneParameter(item), 'col-4': twoParameters(item), 'col-3': threeParameters(item)}"
*ngFor="let param of item.parameters; let arrIndex = index">
<div [ngSwitch]="param">
<input *ngSwitchCase="blabla(param)"
type="text"
class="form-control form-control-sm"
formControlName="{{arrIndex}}"
[placeholder]="getInputPlaceholder(item, arrIndex)"
[ngbTypeahead]="search"
placement="bottom-left">
<div *ngSwitchCase="blablabla(param)">
Search
<app-multi-select
[data]="data"
[displaySmall]="true"
[displayLabel]="false"
[removeValueAfterEvent]="true"
[useInForm]="true"
(onSelectedItemEvent)="selectedItemEventHandler($event, item)"
formControlName="{{arrIndex}}">
</app-multi-select>
</div>
<div *ngSwitchDefault>
<input type="text"
class="form-control form-control-sm"
formControlName="{{arrIndex}}"
[placeholder]="getInputPlaceholder(item, arrIndex)">
</div>
</div>
<button *ngIf="isblabla(item)" type="button" class="btn btn-secondary btn-sm col-2" (click)="onClickEvent(controlItem.value, item, ctrlIndex)" container="body" tooltip="blabla">
<span >
<fa-icon icon="arrows-alt-h" [styles]="{'stroke': 'white', 'color': 'white'}"></fa-icon>
</span>
</button>
<ng-container
*ngTemplateOutlet="arrayItemButtonsTmpl; context: {item:item, ctrlIndex:ctrlIndex, arrayLength: _form.get(item.code).controls.length}">
</ng-container>
</div>
</div>
</form>
multi-select.component.ts
@Component({
selector: 'app-multi-select',
templateUrl: './multi-select.component.html',
styleUrls: ['./multi-select.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => AnnouncementInformationListComponent),
multi: true
}
]
})
multi-select.component.ts
export class MultiSelectComponent implements OnInit, ControlValueAccessor {
value: string;
multi-select.component.ts
writeValue(value: string): void {
this.value = value ? value : ''
}
registerOnChange(fn: any): void {
}
registerOnTouched(fn: any): void {
}
setDisabledState?(isDisabled: boolean): void {
}
Worth noting is that all the other input fields in AnnouncementInformationListComponent.html (which are not using Control Value Accessor) are working just fine. Also, when I google the error message I have problem finding other people who have had the same issue, which I found odd. Any ideas what the problem might be?
Upvotes: 8
Views: 13788
Reputation: 4228
Angular tries to find the writeValue function into your AnnouncementInformationListComponent because you declared it as a reference into your MultiSelectComponent providers array.
Change your provider to :
@Component({
selector: 'app-multi-select',
templateUrl: './multi-select.component.html',
styleUrls: ['./multi-select.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MultiSelectComponent),
multi: true
}
]
})
Upvotes: 5