Reputation: 413
I'm a bit of a beginner in angular 4... tried to search for this many times in the past few months, but got no result, even though it seems the most simple thing.
It's an ionic app. User logs in, the whole user object is saved to localStorage. Have tried several plugins, but went with simple:
window.localStorage.setItem('User', JSON.stringify(user));
user object structure:
export class User {
constructor(
public token?: string,
public user_email?: string,
public email?: string,
public first_name?: string,
public last_name?: string,
public user_roles?: {
ID?: number,
caps?: {
administrator?: boolean,
},
roles?: object,
},
public id?: number,
public device_feedback?: boolean,
public role?: string,
public username?: string,
public billing?: Address,
public shipping?: Address
) {}
}
export class Address {
first_name?: string;
last_name?: string;
company?: string;
address_1?: string;
address_2?: string;
city?: string;
state?: string;
postcode?: string;
country?: string;
email?: string;
phone?: number
}
settings.ts: (I have added ngOnInit and this.platform.ready(){} because thought data is not ready or something...)
export class Settings implements OnInit{
[other vars]
user: User;
constructor(public storage: Storage, private platform: Platform) { }
ngOnInit() {
// this.storage.ready().then(() => {
// this.storage.get("User").then((data) => {
this.platform.ready().then(() => {
let data = window.localStorage.getItem('User');
if (data) {
this.user = JSON.parse(data);
this.email = this.user.user_email;
console.log('user', this.user);
console.log('this.user.user_email', this.user.user_email);
}
});
}
Settings.html
<ion-content>
<ion-list padding>
<ion-list-header>
Title
</ion-list-header>
<ion-item>
<ion-label color="primary" fixed>Email</ion-label>
<ion-input class="in" type="email" [(ngModel)]="user.user_email" disabled="true"></ion-input>
</ion-item>
The user_email is displayed in the console.log, referenced as this.user.user_email and same property gives an error in the HTML... how is this possible? Same in the browser or the device: http://prntscr.com/i8rfhg
I have also tried with user: any
, but got the same result...
How? Why? What am I missing?
Here's the ionic info:
@ionic/cli-utils : 1.19.1
ionic (Ionic CLI) : 3.19.1
global packages:
cordova (Cordova CLI) : 7.1.0
local packages:
@ionic/app-scripts : 1.3.0
Cordova Platforms : none
Ionic Framework : ionic-angular 3.0.1
System:
Android SDK Tools : 25.2.5
Node : v6.11.0
npm : 5.6.0
Thanks a lot!
Upvotes: 2
Views: 1526
Reputation: 1
I use export interface and class.
export interface UserCaps
administrator: boolean;
}
export interface UserRole {
ID: null;
caps: UserCaps;
roles: any;
}
export interface Address {
first_name?: string;
last_name?: string;
company?: string;
address_1?: string;
address_2?: string;
city?: string;
state?: string;
postcode?: string;
country?: string;
email?: string;
phone?: number
}
export interface User {public token: string;
user_email: string;
email: string;
first_name: string;
last_name: string;
user_roles : UserRole;
id: number;
device_feedback: boolean;
role: string;
username: string;
billing: Address;
shipping: Address;
}
export class User {}
And i init my user with new Class()
user = new User();
Upvotes: 0
Reputation: 73721
In ngOnInit
, the callback for this.platform.ready()
is executed asynchronously. Before that, user
is undefined and [(ngModel)]="user.user_email"
causes an error.
You can prevent that error with the safe navigation operator. Since it works only for one-way data binding, you should split [(ngModel)]
in its two parts, [ngModel]
and (ngModelChange)
. In addition to that change, you can keep the input element disabled until user
is initialized, to prevent entering data that will be lost anyway.
[ngModel]="user?.user_email" (ngModelChange)="setUserEmail($event)" [disabled]="!user"
with the component method:
setUserEmail(value: string): void {
if (this.user) {
this.user.user_email = value;
}
}
The code is illustrated in this stackblitz, where the user
object is initialized after a few seconds.
Upvotes: 1
Reputation: 36
you don't have instance of User in this.user.
export class User {
public token: string;
public user_email: string;
public email: string;
public first_name: string;
public last_name: string;
public user_roles : Object = {
ID: null,
caps: {
administrator: false,
},
roles: {},
};
public id: number;
public device_feedback: boolean;
public role: string;
public username: string;
public billing: Address;
public shipping: Address;
public set(data:any){
if(!data){
return;
}
this.token = data.token;
this.user_email = data.user_email;
this.email = data.email;
this.first_name = data.first_name;
this.last_name = data.last_name;
this.id = data.id;
this.device_feedback = data.device_feedback;
this.role = data.role;
this.username = data.username;
this.billing = data.billing;
this.shipping = data.shipping;
this.user_roles = data.user_roles;
} }
and
export class Settings implements OnInit{ [other vars]
user: User = new User(); constructor(public storage: Storage, private platform: Platform) { }
ngOnInit() {
// this.storage.ready().then(() => {
// this.storage.get("User").then((data) => {
this.platform.ready().then(() => {
this.user.set(window.localStorage.getItem('User'));
});
}
Upvotes: 1
Reputation: 2455
You are trying to access the property user_email of your user object while it's null / before it's initialized.
Try:
user: User = {}; // initial value
Or:
<ion-list padding *ngIf="user">
<ion-list-header>
Title
</ion-list-header>
<ion-item>
<ion-label color="primary" fixed>Email</ion-label>
<ion-input class="in" type="email" [(ngModel)]="user.user_email" disabled="true"></ion-input>
</ion-item>
Upvotes: 1