Ionic 2 - ngOnInit event - get storage issue - ionic-framework

I am storing a user id in the storage and trying to get the stored id when the page is loaded.
Below is the code snippet
constructor(
private nav: NavController,
private auth: AuthService,
public clockservice: ClockService,
private alertCtrl: AlertController,
private loadingCtrl: LoadingController,
public storage: Storage
) {
storage.get('name').then(val => {
this.username = val;
})
storage.get('id').then(val => {
this.userid = val;
console.log(this.userid);
})
}
ngOnInit() {
console.log("inside");
console.log(this.userid);
getStatus();
}
getStatus() {
this.showLoading();
this.clockservice.getinoutstatus(this.userid).subscribe(
result => {
if (result.success) {
// do something here
} else {
this.showError("API Error.");
}
this.loading.dismiss();
},
error => {
this.showError("API Error.");
}
);
}
The issue I face is the user id is not received in the ngOnInit event. The console log shows the ngOnInit is called even before the user id is received in the constructor.
console log:
inside
1
How to make sure that is ngOnInit even is called after all the get values received in the constructor?

The simplest solution would be to perform a Promise.all to wait for both storage values to be retrieved and to then call getStatus:
ngOnInit() {
Promise.all([
this.storage.get('name'),
this.storage.get('id')
])
.then(([name, id]) => {
this.username = name;
this.userid = id;
getStatus();
})
.catch(error => {
this.showError("Storage Error.");
});
}
Retrieving the storage values in the constructor would be okay, but - looking at the implementation - it seems likely that getStatus should not be called before ngOnInit. So move the storage calls and the promise chain into ngOnInit

Related

I am getting error while passing parameters from service

Here is the code and I am receiving an error while passing this parameter from services.
export class CardsPage {
currentItems: Item[];
id: any;
getData: Object;
categories:any;
constructor(public navCtrl: NavController, public api:Api, navParams:
NavParams, items: Items, public http: HttpClient) {
this.id = navParams.get('idName') ||'';
console.log(this.id);
this.api.getCategoryPosts(this.id).subscribe(data=>{
console.log(data)
this.getData = data
},err=>{
console.log(err)
})
}
openItem(item){
this.navCtrl.push('ItemDetailPage', {
itemName: item
});
}
}
Here is my Ts file:
getCategoryPosts(category: any) {
return this.http.get(`${this.api_url}/posts?
categories=${category.id}`);
}
The error that i am receiving is Reference error: category is not defined Reference error. Category is not defined at new CardsPage
Hello just use ionViewWillEnter to get your parameter and no need to use OR operation while getting parameter so here is the solution.
ionViewWillEnter(){
this.id = navParams.get('idName')
}
then use ionViewDidEnter to fetch data through service.
ionViewDidEnter(){
this.api.getCategoryPosts(this.id).subscribe(data=>{
console.log(data)
this.getData = data
},err=>{
console.log(err)
})
}

Cannot use namespace 'NavController'',NgZone',Google,as a type

I am new to ionic app developer, and I am facing this issue: when I open one Component, it is showing error messages, i.e, cannot use namespace as type ionic(NgZone,NavController and googlePlus). Why am I getting this error message?
Here is my code:
export class HomePage {
userProfile: any = null;
zone: NgZone;
constructor(public navCtrl: NavController, private googlePlus: GooglePlus) {
this.zone = new NgZone({});
firebase.auth().onAuthStateChanged( user => {
this.zone.run( () => {
if (user){
this.userProfile = user;
} else {
this.userProfile = null;
}
});
});
}
}
Maybe you forgot to update your project's package. Please try with:
npm install / npm update
Try the Below code : ( The NgZone object can be created as below )
export class HomePage {
userProfile: any = null;
zone: NgZone;
constructor(public navCtrl: NavController, private googlePlus: GooglePlus, private ngZone: NgZone) {
this.zone = ngZone;
firebase.auth().onAuthStateChanged( user => {
this.zone.run( () => {
if (user){
this.userProfile = user;
} else {
this.userProfile = null;
}
});
});
}
}

Ionic Searchbar with PHP API

It works but i anot getting the results it should sort. I am getting the same results regardless what i type in the searchbar
I want it to sort like autocomplete. to show results of what i type in the search bar
search.ts
#Component({ selector: "page-search", templateUrl: "search.html" })
export class SearchPage {
filter: string = '';
public userDetails: any;
public resposeData: any;
public dataSet: any;
public userSet: any;
public mediaSet: any;
public noRecords: boolean;
userPostData = {
uid: "",
token: "",
username: "",
bio: ""
};
constructor(
public common: Common,
public navCtrl: NavController,
public app: App,
public menu: MenuController,
public authService: AuthService,
public http: Http,
platform: Platform,
statusBar: StatusBar,
splashScreen: SplashScreen
) {
this.initializeItems();
this.mostmediaList();
}
initializeItems() {
return this.userPostData;
}
getItems(ev: any) {
this.initializeItems();
let val = ev.target.value;
if (val && val.trim() != '') {
this.authService.postData(this.userPostData, "userGroupSearch").then(
result => {
this.resposeData = result;
if (this.resposeData.allArtistsData) {
this.userSet = this.resposeData.allArtistsData;
console.log(this.userSet);
} else {
console.log("No access");
}
},
);
}
}
Since your code is wrapped into
if (this.resposeData.items) {
//some code
}
we know for sure that this.resposeData is not an array, since it has an items member (otherwise your code inside the if would not be executed and hence you would not get an error as in the case we have).
Since you call the parameter items at
this.userSet = this.resposeData.filter((items) => {
//some code
};
it is safe to assume that you wanted to filter this.resposeData.items instead of this.resposeData. So, you will need to make sure it is an array at the if
if (this.resposeData.items && Array.isArray(this.resposeData.items)) {
//some code
}
and filter this.resposeData.items instead of this.resposeData:
this.userSet = this.resposeData.items.filter((items) => {
//some code
};

Ionic2 navController pop with params (CallBack)

I want to make a callback between two page.
In the page 1, i have this code:
DataInfo= [
{
Price: 0,
ClosePrice: 0,
UpdateTime:"",
DefaultPrice:0
}
]
GetClosePrice(i):number{
return DataInfo[i].ClosePrice;
}
i want to get the value of 'i' from the page 2, How can i load the function GetClosePrice() when the navcontroller return to the page 1 (this.navCtrl.pop())
SOURCE PAGE CLASS
this.navCtrl.push(Page,
{
data: this.data,
callback: this.getData
});
getData = data =>
{
return new Promise((resolve, reject) => {
for (let order of orders) {
this.data = data;
}
resolve();
});
};
TARGET PAGE CLASS
constructor(public navCtrl: NavController, public navParams: NavParams)
{
this.callback = this.navParams.get('callback');
this.data = this.navParams.get('data') || [];
}
sendData(event: any): void
{
this.callback(this.data).then( () => { this.navCtrl.pop() });
}
TARGET PAGE TEMPLATE
<button ion-button (click)="sendData($event)">
I answered similar question in Ionic forum. I just used Events listeners to achieve this behaviour.
MainPage-
import { NavController, Events } from 'ionic-angular';
import { OtherPage } from '../other/other';
export class MainPage{
constructor(private navCtrl: NavController,
private events: Events) { }
private pushOtherPage(){
this.events.subscribe('custom-user-events', (paramsVar) => {
// Do stuff with "paramsVar"
this.events.unsubscribe('custom-user-events'); // unsubscribe this event
})
this.navCtrl.push(OtherPage); // Push your "OtherPage"
}
}
OtherPage-
export class OtherPage {
// Under some function
this.navCtrl.pop().then(() => {
// Trigger custom event and pass data to be send back
this.events.publish('custom-user-events', myCustomParams);
});
}
Try this one - ionic2 pop with params

Angular 2 data service

I'm building an observable data service based on the following article: https://coryrylan.com/blog/angular-2-observable-data-services
In the article he used an array as an example, here I will use the user object since I'm developing the user service.
Here's what I got:
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Events, SqlStorage, Storage } from 'ionic-angular';
import { Subject } from 'rxjs/Subject';
export interface DataStore {
user: Object
}
#Injectable()
export class UserService {
private baseUrl: string;
private storage: Storage;
private _user$: Subject<Object>;
private dataStore: DataStore;
constructor(
private http: Http
) {
this.baseUrl = 'http://localhost:3000';
this.storage = new Storage(SqlStorage);
this._user$ = <Subject<Object>>new Subject();
this.dataStore = {
user: { name: '' }
};
}
set user$(user: Object) {
this.storage.set('user', JSON.stringify(user));
this.dataStore.user = user;
this._user$.next(this.dataStore.user);
}
get user$() {
return this._user$.asObservable();
}
loadUser() {
return this.storage.get('user').then(
((user: string): Object => {
this.dataStore.user = JSON.parse(user);
this._user$.next(this.dataStore.user);
return this.dataStore.user;
})
);
}
login(accessToken: string) {
return this.http
.post('http://localhost:3000/login', { access_token: accessToken })
.retry(2)
.map((res: Response): any => res.json());
}
logout(): void {
this.storage.remove('user');
}
}
To authenticate I call the login() function and set the user data if everything ok.
this.userService.login(this.data.accessToken)
.subscribe(
(user: Object) => {
this.userService.user$ = user;
this.nav.setRoot(EventListComponent);
},
(error: Object) => console.log(error)
);
I feel it is better set the user data inside the service. I could do the following:
login(accessToken: string) {
return this.http
.post('http://localhost:3000/login', {
access_token: accessToken
})
.retry(2)
.map((res: Response): any => res.json())
.subscribe(
(user: Object) => {
this.userService.user$ = user;
this.nav.setRoot(EventListComponent);
},
(error: Object) => console.log(error)
);
}
But I won't be able to subscribe to the login() function in the component since it's already subscribed. How could I redirect the user if everything ok or show an alert if anything goes wrong in the component but setting the user inside the service?
In the main component I load the user data and set the rootPage:
this.userService.loadUser().then(
(user: Object) => this.rootPage = EventListComponent,
(error: Object) => this.rootPage = LoginComponent
);
I thought that calling the loadUser() function at this time I would not have to call it again, but I have to call it in all components that I need the user data:
this.user = this.userService.user$;
this.userService.loadUser();
I don't think the service is the way it should, what could I improve? Is there any better way to achieve what I want? Any example or idea?