8

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?

1 Answer 1

5

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
    }
  ]
})
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.