Search code examples
angulartypescriptngoninit

Cannot read property of undefined error even though the binding is working


So, I have a dropdown in my web app that I hooked up to my service api call that will populate the dropdown with list of locations.

I created the service and set up the Observable using httpclient.

Then I call the service to fetch the results of api call and bind to my location property.

E.g. In my component.ts file inside of ngOnInit() I have this:

ngOnInit() {
    this._transactionService.getLocations('User').subscribe(data => this.location = data);
    }

In my component.html file:

<select [ngModel]="null" formControlName="location">
            <option value="null" disabled selected>{{'SelectLocation' | translate}}</option>
            <option *ngFor="let store of location._storeList" [ngValue]="store._storeKey">{{ store._storeName }}</option>
        </select>

When I load the page, I notice briefly, it loads weird for like a fraction of a sec, then correct itself and load properly. I check my dropdown and I see it correctly binds the list of locations I want and I'm able to select it just fine. Looks good! However, when I do inspect element > console, I see this error:

ERROR TypeError: Cannot read property '_storeList' of undefined
    at Object.eval [as updateDirectives] (PortalComponent.html:11)
    at Object.debugUpdateDirectives [as updateDirectives] (core.js:14651)
    at checkAndUpdateView (core.js:13798)
    at callViewAction (core.js:14149)
    at execComponentViewsAction (core.js:14081)
    at checkAndUpdateView (core.js:13804)
    at callViewAction (core.js:14149)
    at execEmbeddedViewsAction (core.js:14107)
    at checkAndUpdateView (core.js:13799)
    at callViewAction (core.js:14149)

So while the binding and results works fine, I'm not sure why I'm getting that console error. I think it's related to the Angular lifecycle of ngOnInit() but I'm not sure how to properly fix this issue. Should I be calling my service instead of ngOnInit() or elsewhere? What is best practice to fix this issue?


Solution

  • Because location is loaded asynchronously, use, it is undefined at the first time Angular loads executes the template.

    The solution is to use the Safe Navigation (aka elvis ?.) operator:

    <option *ngFor="let store of location?._storeList" [ngValue]="store._storeKey">{{ store._storeName }}</option>