javascript - Typescript no puede acceder al objeto JSON (Angular2)
Tengo el problema más extraño.
Estoy recibiendo un objeto JSON
{"login":"admin","name":"Admin"}
Y lo que estoy haciendo en el código es:
private _userData: User;
...
private getUserData() {
this._userInfoService.getUserInfo()
.subscribe(
data => {
this._userData = data.json(); // (using <User> data.json() changes nothing
},
err => alert(err)
);
}
Dónde está el tipo de usuario
export interface User {
login: string;
name: string;
}
Pero cuando intento acceder a esos campos en HTML con Angular:
<p>{{ _userData.login }}</p>
<p>{{ _userData.name }}</p>
Estoy recibiendo algunos errores desagradables en la consola como: Error: EXCEPCIÓN: TypeError: l__userData21 es nulo en [{{ _userData.login }} en UserHomeComponent@8:7]
aunque puedo ver claramente cuando estoy haciendo console.log sobre este objeto: Object { login: "admin", name: "Admin" }
Lo hice exactamente igual con otra clase y funciona allí. Lo que es aún más interesante es que cuando cambio el código ligeramente, así:
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)
);
}
y ver:
<p>{{ _login }}</p>
<p>{{ _name }}</p>
¡Entonces todo funciona perfectamente! No tengo absolutamente ninguna idea de lo que está pasando (intenté convertir data.json() pero eso no cambia nada).
@Editar: La otra clase, donde funciona, es:
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
y en la vista:
<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>
Respuesta #1
los datos del usuario llegan de forma asincrónica, lo que significa que es indefinido antes. esto es cuando Angular lanzará una excepción porque haces indefinido.login
lo que tendrás que hacer es indicar que userData puede ser indefinido usando el operador Elvis.
prueba esto:
<p>{{ _userData?.login }}</p>
<p>{{ _userData?.name }}</p>
alternativamente, puedes usar un *ngIf envolvente, por ejemplo
por cierto, esto no tiene nada que ver con TypeScript, sino con Angular2 y JavaScript. por favor, edita tu título correctamente
Respuesta #2
Intentas establecer un enlace de datos a _userData.login y NO a _userData
Veo dos posibles errores:
Primero: - Como Patrick ya escribió, tus datos llegan de manera asincrónica, lo que significa que _userData.login es indefinido cuando intentas establecer el enlace de datos, porque _userData es indefinido (y no tiene un valor nulo predeterminado). Por lo tanto, el enlace de datos falla y no recibirás notificaciones ni actualizaciones cuando más adelante lo actualices. - Sin embargo, tu segundo ejemplo funciona porque _name y _login no están indefinidos sino que están llenos con su valor NULL (supongo que una cadena vacía). Debido a eso, el enlace de datos se establece correctamente.
Segundo: - El segundo error posible es una vinculación de referencias de objetos y atributos de objetos. - Dependiendo de cómo se implementen los escuchas de cambios, en realidad es una diferencia entre obj1=newObject y obj1.attr1=newValue. Por lo tanto, cambiar solo el objeto en sí no activaría el escucha de cambios en un solo atributo.
Sin embargo, apostaría a que es la primera posibilidad. Podrías probar esto inicializando el objeto User con un objeto vacío en el constructor...
