Ionic 2 Page Change Subscription - ionic2

How can I subscribe to page changes in Ionic 2? I'd just like to log page names/titles globally. Is there an event I can subscribe to?

create a service
import {Injectable} from '#angular/core';
import {Subject} from 'rxjs/Rx';
#Injectable()
export class RouteNamesService{
constructor(){
}
public name = new Subject();
setRouteName(name){
this.name.next(name);
}
}
in app.component.ts
subscribe to
this.routeNamesService.name.subscribe(name => this.routeName = name);
when you enter in to a component then fire
this.routeNamesService.setRouteName("Settings");
(or) in app.component.ts
#ViewChild(Nav) nav: Nav;
ngAfterViewInit() {
this.nav.viewDidEnter.subscribe((data) => {
console.log(data);
});
}
in data you can get component name

Related

Ionic 2, Tab content gets rendered before method execution in main page is completed

I have a dashboard page. and this page has two tabs to show recent sales and recent inventory.
When user inters dashboard, loadDashboardItems method is called.
My dashboard.ts
import { Component } from '#angular/core';
import {NavController, NavParams, LoadingController } from 'ionic-angular';
import {Storagehelper} from '../../providers/storagehelper';
import { DashboardrecentsalesPage } from '../dashboardrecentsales/dashboardrecentsales';
import { DashboardrecentinventoryPage } from '../dashboardrecentinventory/dashboardrecentinventory';
import {Webservice} from '../../providers/webservice';
/**
* Generated class for the Dashboard page.
*
* See http://ionicframework.com/docs/components/#navigation for more info
* on Ionic pages and navigation.
*/
#Component({
selector: 'page-dashboard',
templateUrl: 'dashboard.html',
})
export class DashboardPage {
private recentSales;
private recentInventory;
private loading;
private ajaxRequest;
constructor(public navCtrl: NavController, public navParams: NavParams, private storagehelper: Storagehelper, public loadingCtrl: LoadingController, public webservice: Webservice) {
this.loadDashboardItems();
this.recentSales = DashboardrecentsalesPage; //This is the default tab in dashboard page
this.recentInventory = DashboardrecentinventoryPage;
}
ionViewWillLeave(){
if(this.loading) this.loading.dismiss().catch(() => {});
if(this.ajaxRequest!=undefined){
this.ajaxRequest.unsubscribe();
}
}
private loadDashboardItems(){
//HERE API REQUEST IS MADE AND data is saved to Localstorage
}
}
And default tab dashboardrecentsales.ts
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams, Tabs } from 'ionic-angular';
import {Storagehelper} from '../../providers/storagehelper';
/**
* Generated class for the Dashboardsummaryitems page.
*
* See http://ionicframework.com/docs/components/#navigation for more info
* on Ionic pages and navigation.
*/
#Component({
selector: 'page-dashboardrecentsales',
templateUrl: 'dashboardrecentsales.html',
})
export class DashboardrecentsalesPage {
private RecentItems;
constructor(public navCtrl: NavController, public navParams: NavParams, private storagehelper: Storagehelper) {
this.getDashboardItems();
}
getDashboardItems(){
this.RecentItems = this.storagehelper.getStorageItem("RecentItems");
//This RecentItems property is used to render view dashboardrecentsales
}
}
Here in dashboard.ts the API request is made and data are saved in LocalStorage
And 'dashboardrecentsales.ts' fetches data from local storage and renders view to show on tab.
PROBLEM
The problem I have is if user is accessing dashboard page for the first time, Even though data are saved in localstorage, the tab page doesn't get any data from localstorage.
It seems Tab is rendered before execution of loadDashboardItems method of dashboard page gets completed.
I tried putting
this.recentSales = DashboardrecentsalesPage; //This is the default tab in dashboard page
this.recentInventory = DashboardrecentinventoryPage;
inside loadDashboardItems method when everything is saved to localstorage, but no tab view was rendered at all.
Can anybody suggest what can I do in this scenario.
For your case, you can make use of ionViewDidLoad() to load your dashboard items. Try something like this,
ionViewDidLoad(){
this.loadDashboardItems();
}
check this documentation to know more about all the predefined NavController methods
Hope that helps!
Anyway I solved it using event.publish and event.subscribe. More info Here
The sample code from the link. I used this logic to refresh the contents.
import { Events } from 'ionic-angular';
// first page (publish an event when a user is created)
constructor(public events: Events) {}
createUser(user) {
console.log('User created!')
events.publish('user:created', user, Date.now());
}
// second page (listen for the user created event after function is called)
constructor(public events: Events) {
events.subscribe('user:created', (user, time) => {
// user and time are the same arguments passed in `events.publish(user, time)`
console.log('Welcome', user, 'at', time);
});
}

Ionic 2 : EXCEPTION: Unexpected token < in JSON at position 0

I want to send data to my database and when i click on submit button, i get this exeption : EXCEPTION: Unexpected token < in JSON at position 0
I really dont know what to do :/ you can check my code on my github: https://github.com/majlo23/makeorder-ionic
and here is my PHP code: https://github.com/dmikulasova/make-order_server
I had the same error but when i changed the serve response format to JSON, it worked for me.
More details
Node example:
app.get('/', function(req, res, next) {
return res.status(200).json({
message: "success"
});
});
Ionic 2
I generated a service.ts file to define my HTTP request method to be shared with all components.
I defined function load that return an Observable
import {Injectable} from '#angular/core';
import 'rxjs/add/operator/map';
import {Http,Response} from '#angular/http';
import {BackendURL} from '../utils/backendURL';
#Injectable()
export class HomeService {
constructor(private http: Http) {
}
load() {
return this.http.get(BackendURL.host).map((res:Response) => res.json()).catch(BackendURL.handleError);
}
}
In my component, i inject the service and i subscribe to the observable.Now you should see the response logged in the console.
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import {HomeService} from '../../services/home.service';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(public navCtrl: NavController,public hs:HomeService) {
console.log('constructor HomePage');
this.hs.load().subscribe((data:any) => console.log('constructor HomePage data',data));
}
}

Ionic 2 - Add a component dynamically to app root

I'm trying to add a custom component dynamically (from a directive) into my Ionic 2 app root...
I've tried many things, but nothing works!
I know that I could add a container with an id to hold my custom component and reach it through an Input in my directive, but I don't want to use that solution.
I need to be able to add any custom component into app root.
This is my last attempt:
import { Directive, ElementRef,
ComponentFactoryResolver,
ViewContainerRef,
ApplicationRef
} from '#angular/core';
import { App, ViewController } from 'ionic-angular';
import { MyComponent } from '../../components/myComponent/myComponent';
#Directive({
selector: '[myDirective]',
host: {
'(click)': 'onClick()',
}
})
export class MyDirective {
myComponent: any;
constructor( private el: ElementRef,
private app: App,
private appRef: ApplicationRef,
private vcr: ViewContainerRef,
private componentFactoryResolver: ComponentFactoryResolver
) {
this.myComponent = this.componentFactoryResolver.resolveComponentFactory(MyComponent);
}
onClick() {
this.app._appRoot._overlayPortal._viewport.createComponent(this.myComponent);
}
}
It should create my component as a sibling of _overlay elementin app root, but I only receive an error message:
No provider for ViewController
What am I doing wrong? Any suggestion or any other solution?

Loading config before starting to construct/load rootPage

Im building a ionic 2 rc0 app. My rootPage depends on some configuration I have to load before I start my App. I'm using a provider called Config all over over the application. How can I delay/wait until configs loaded before constructing my Home page component. I need the configs in the constructor of Home. Is there sth. like a preloading module from ionic for situation like that ?
Is that even the best location for tasks like that ?
My Config module uses
http.get(../assets/config/config.json)
.toPromise()
.then(res => this.data = res);
to load the json file locally into data object of of my Config provider. And my code in app.component.ts fires a the function config.loadDefault() to load these default settings from the config.json file for the application .....
app.components.ts
import { Component } from '#angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from 'ionic-native';
import { Home } from '../pages/home/home';
import { Config } from '../providers/config/config';
#Component({
template: `<ion-nav [root]="rootPage"></ion-nav>`
})
export class LoddenApp {
public rootPage = Home;
constructor(
public platform : Platform,
public config : Config
){
// loading config
config.loadDefault()
.then(data => {
console.log(data);
return config.loadSettingsFromDB();
})
.catch(err => {
console.log("error occured while loading config:");
console.log(err);
});
platform.ready().then(() => {
...
});
}
}
By not defining the rootPage until i got back my promise response, I can hold back the constructor of my Home page from firing.
...
export class LoddenApp {
public rootPage : any; // hold back
constructor(
...
Then inside the then() block, i can set the rootPage of my app.
this.rootPage = Home; // Home is the Homepage component
I am not sure this is the best way to do. But one option is to hide the splash screen after your data gets loaded.
import {Splashscreen} from 'ionic-native';
constructor(
public platform : Platform,
public config : Config
){
platform.ready().then(() => {
// loading config
config.loadDefault()
.then(data => {
console.log(data);
return config.loadSettingsFromDB();
})
.catch(err => {
console.log("error occured while loading config:");
console.log(err);
});
Splashscreen.hide();
});
}

ionic 2 TypeError: self.context.doInfinite is not a function

I am trying to load more data from the server and i am getting error in a console
zone.js:260
Uncaught EXCEPTION: Error in build/pages/home/home.html:30:23
ORIGINAL EXCEPTION: TypeError: self.context.doInfinite is not a function
ORIGINAL STACKTRACE:
TypeError: self.context.doInfinite is not a function
at DebugAppView._View_HomePage0._handle_ionInfinite_25_0..
home.ts has the following codes
import {Component} from '#angular/core';
import {NavController} from 'ionic-angular';
import {Http} from '#angular/http';
import 'rxjs/add/operator/map';
import {JobService} from '../job/job';
import {JobPage} from '../services/JobService';
#Component({
templateUrl: 'build/pages/home/home.html',
providers:[JobService]
})
export class HomePage {
public posts:any = [];
private start:number=0;
constructor(private navCtrl: NavController, public peopleService:PeopleService) {
this.loadPeople();
}
loadPeople() {
return new Promise(resolve => {
this.peopleService.load(this.start)
.then(data => {
for(let kazitz of data) {
this.posts.push(kazitz);
}
resolve(true);
});
});
}
doInfinite(infiniteScroll) {
console.log('doInfinite, start is currently '+this.start);
this.start+=5;
this.loadPeople().then(()=>{
infiniteScroll.complete();
});
}
}
Now, error says doInfinite is not a function while it is a function you see above, i am getting this error while the app tries to load more data.. in home.html normal ionic 2 load more codes i took from ionic framework docs
<ion-infinite-scroll (ionInfinite)="doInfinite($event)">
<ion-infinite-scroll-content
loadingSpinner="bubbles"
loadingText="Loading more...">
</ion-infinite-scroll-content>
</ion-infinite-scroll>
Any help will be appreciated!
I had the same issue, and it only worked when i added this.doInfinite(); to the Constructor() like this:
Constructor(){
this.doInfinite();
}
I cannot guarantee it will work, and I apologise if it doesn't. I am honestly still perplexed by it. Good luck!