Angular: ERROR TypeError: Cannot read properties of null (reading 'writeValue') when using...

Discussão em 'Angular' iniciado por AlejoDev, Abril 14, 2025.

  1. AlejoDev

    AlejoDev Guest

    I'm implementing a standalone component in Angular that wraps the gmpx-place-autocomplete web component from Google Maps Platform and implements the ControlValueAccessor interface to use it within a reactive form. When I try to use the component in my form, I receive the following error:

    ERROR TypeError: Cannot read properties of null (reading 'writeValue')
    at Yo (forms.mjs:3236:21)
    at e.addControl (forms.mjs:5173:7)
    at e._setUpControl (forms.mjs:5751:41)
    at e.ngOnChanges (forms.mjs:5698:30)
    at e.Y0 (core.mjs:3136:10)
    at qp (core.mjs:4199:10)
    at bb (core.mjs:4226:5)
    at Im (core.mjs:4183:9)
    at js (core.mjs:4138:5)
    at mv (core.mjs:12111:9)


    My Current Implementation

    Google Place Autocomplete Component (standalone):

    TS

    import { Component, ElementRef, forwardRef, OnInit, ViewChild, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
    import { CommonModule } from '@angular/common';
    import { ControlValueAccessor, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms';
    import { GoogleMapsLoaderService } from 'src/app/_services/google-maps-loader.service';

    @Component({
    selector: 'app-google-place-autocomplete',
    templateUrl: './google-place-autocomplete.component.html',
    styleUrls: ['./google-place-autocomplete.component.scss'],
    standalone: true,
    imports: [
    CommonModule,
    ReactiveFormsModule
    ],
    providers: [
    {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => GooglePlaceAutocompleteComponent),
    multi: true,
    }
    ],
    schemas: [CUSTOM_ELEMENTS_SCHEMA]
    })
    export class GooglePlaceAutocompleteComponent implements ControlValueAccessor, OnInit {
    @ViewChild('autocomplete', { static: false }) autocompleteRef!: ElementRef;

    value: string = '';
    disabled = false;
    onChange = (value: any) => { };
    onTouched = () => { };

    constructor(private googleMapsLoader: GoogleMapsLoaderService) { }

    async ngOnInit() {
    await this.googleMapsLoader.load();
    }

    writeValue(value: string): void {
    this.value = value;
    this.updateComponentValue();
    }

    registerOnChange(fn: any): void {
    this.onChange = fn;
    }

    registerOnTouched(fn: any): void {
    this.onTouched = fn;
    }

    setDisabledState(isDisabled: boolean): void {
    this.disabled = isDisabled;
    if (this.autocompleteRef?.nativeElement) {
    this.autocompleteRef.nativeElement.disabled = isDisabled;
    }
    }

    onPlaceSelected(event: any) {
    const place = event.detail?.place;
    this.value = place?.formattedAddress || '';
    this.onChange(this.value);
    this.onTouched();
    }

    private updateComponentValue(): void {
    if (this.autocompleteRef?.nativeElement) {
    if (typeof this.autocompleteRef.nativeElement.setValue === 'function') {
    this.autocompleteRef.nativeElement.setValue(this.value);
    } else {
    this.autocompleteRef.nativeElement.value = this.value;
    }
    }
    }
    }


    HTML

    <gmpx-place-autocomplete
    #autocomplete
    style="width: 100%"
    [value]="value"
    (gmpx-placechange)="onPlaceSelected($event)">
    </gmpx-place-autocomplete>


    Usage in Form Component:

    @Component({
    selector: 'app-location-form',
    standalone: true,
    imports: [
    CommonModule,
    ReactiveFormsModule,
    GooglePlaceAutocompleteComponent
    ],
    template: `
    <form [formGroup]="locationForm" (ngSubmit)="onSubmit()">
    <app-google-place-autocomplete formControlName="address"></app-google-place-autocomplete>
    <button type="submit">Save</button>
    </form>
    `
    })
    export class LocationFormComponent implements OnInit {
    locationForm = this.fb.group({
    address: ['', Validators.required]
    });

    constructor(private fb: FormBuilder) {}

    ngOnInit(): void {}

    onSubmit(): void {
    if (this.locationForm.valid) {
    console.log(this.locationForm.value);
    }
    }
    }


    Question: Why am I receiving this error and how can I fix it? Is there any known issue with standalone components implementing ControlValueAccessor? Any help would be greatly appreciated.

    Continue reading...

Compartilhe esta Página