简体   繁体   中英

Typescript can't access JSON object (Angular2)

I have the weirdest problem.

I'm receiving a JSON object

{"login":"admin","name":"Admin"}

And what I'm doing in code is:

private _userData: User;
...
private getUserData() {
    this._userInfoService.getUserInfo()
        .subscribe(
            data => {
                this._userData = data.json(); // (using <User> data.json() changes nothing
            },
            err => alert(err)
        );
}

Where User type is

export interface User {
    login: string;
    name: string;
}

But when I'm trying to access those fields in html with angular:

<p>{{ _userData.login }}</p>
<p>{{ _userData.name }}</p>

I'm getting some nasty errors in console like: Error: EXCEPTION: TypeError: l__userData21 is null in [{{ _userData.login }} in UserHomeComponent@8:7]

although I can clearly see when I'm doing console.log on this object: Object { login: "admin", name: "Admin" }

I did it exactly the same with other class and it works there. What is even more interesting is that when I slightly change the code, like this:

private _name: string;
private _login: string;
...
private getUserData() {
    this._userInfoService.getUserInfo()
        .subscribe(
            data => {
                this._name = (<User> data.json()).name;
                this._login = (<User> data.json()).login;
            },
            err => alert(err)
        );
}

and view:

<p>{{ _login }}</p>
<p>{{ _name }}</p>

Then everything works perfectly! I have absolutely no clue what is happening (tried to cast data.json() to but that changes nothing.)

@Edit: The other class, where it works is:

export interface LoginData {
    access_token: string;
    token_type: string;
    refresh_token: string;
    expires_in: number;
    scope: string;
}


private _loginData = <LoginData> JSON.parse(sessionStorage.getItem("loginData")); //tried this also with User, doesn't work

and in the view:

<p>access_token: {{ _loginData.access_token }}</p>
<p>token_type: {{ _loginData.token_type }}</p>
<p>refresh_token: {{ _loginData.refresh_token }}</p>
<p>expires_in: {{ _loginData.expires_in }}</p>

the user data comes in asynchronously which means that it is undefined before. this is when angular will throw an exception because you do undefined .login

what you will have to do is to indicate that userData may be undefined by using the elvis-operator.

try this:

<p>{{ _userData?.login }}</p>
<p>{{ _userData?.name }}</p>

alternatively you can use a wrapping *ngIf for example

btw this has nothing to do with typescript, but with angular2 and javascript. please edit your title properly

You try to establish a databinding to _userData.login and NOT to _userData

I see two possible errors:

First: - As Patrick already wrote, you data arrives asynchronously, which means _userData.login is undefined when you try to establish the data-binding, because _userData is undefined (and has no default null value). Therefore the data-binding fails and you won't be informed / get any updates when you later update it - Your second example works, how ever, because _name and _login are not undefined but filled with their NULL value (I guess an empty string). Because of that the data binding is actually successfully estasblished

Second: - Second possible error is a binding of object references and object attributes. - Depending on how the change listener are implemented it is actually a difference between obj1 = newObject and obj1.attr1 = newValue . So changing just the object itself wouldn't trigger the change listener on a single attribute.

How ever, I'd bet it's the first possibility. You could test this by initializing the User object with an empty object in the constructor...

Try adding something like this in front of the <p> tags:

<div *ngFor="let uData of _userDat;">

and then

<p>{{uData.login}} 
</p></div>

OR

<div *ngIf="user">
<p>{{_userDat.login}}</p>

Use ? for safe navigation.

<p>{{ _userData?.login }}</p>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM