I have a project on Android that I would like to change the root page dynamically determined if a user is logged in or not.
In the app.component.ts. I am checking the local storage for a flag that determines if the user is logged in. If they are, it takes them to the 2nd page and doesn't show a login page. If they aren't, it shows them a login page.
My problem is that the local storage GET is a Promise and it finishes up the constructor of app.component.ts before it has an opportunity (it goes to the login screen and shows it) then when the Promise is finished it switches to the 2nd screen. I don't want to show the login screen at all if they are already logged in.
I've tried everything and can't seem to figure this out. How can I change the root page that loads based on the status of a value in the local storage?
New solution, now a little more ellegant. I only set the root programatically after I reach storage and check whether it should show Home or Login.
#Component({
template: `<ion-nav #nav></ion-nav>`
)
export class MyApp {
#ViewChild('nav') nav: Nav;
constructor(platform: Platform, storage: Storage) {
this.storage.get('isLogged').then(logged => {
if (logged) {
this.nav.setRoot(HomePage);
} else {
this.nav.setRoot(LoginPage);
}
});
}
Before Edit
Not an ellegant solution, and I will keep around to see if there is a better way, but in my case I postponed the exibition of the root with a *ngIf.
My AppComponent is something like this:
#Component({
template: `<ion-nav *ngIf="showRoot" [root]="rootPage"></ion-nav>`
})
export class MyApp {
rootPage:any = LoginPage;
showRoot = false;
constructor(platform: Platform, storage: Storage) {
this.storage.get('isLogged').then(logged => {
if (logged) {
this.rootPage = HomePage;
}
this.showRoot = true;
});
}
}
Related
I want to know which function is called when we click ion-navbar back button by default in ionic 3.
I want to call the same function on hardware back button click.
You can use registerBackButtonAction of Platform Service.
You can override hardware back button action as below inside app.component.ts.
Remember to call registerBackButtonAction after Platform.ready().
import { Platform, App } from 'ionic-angular';
#Component({
templateUrl: 'app.html'
})
export class MyApp {
constructor(public platform: Platform, private app: App) {
this.platform.ready().then(() => {
this.platform.registerBackButtonAction(() => {
let nav = this.app.getActiveNav()
if (nav.canGoBack()) {
// If there are pages in navigation stack go one page back
// You can change this according to your requirement
nav.pop();
} else {
// If there are no pages in navigation stack you can show a message to app user
console.log("You cannot go back");
// Or else you can exit from the app
this.platform.exitApp();
}
});
});
}
}
Hope this will help you.
I am making a login app with MySQL database. I have already done login but when I close my app or press the back button of my mobile, it starts from login page again.
I tried to save the login data in local storage but it does not work. I have been searching online for some answers but I can't seem to find the solution.
Below is my code
login.ts
signIn(page) {
if(this.username.value==""){
let alert = this.alertCtrl.create({
title:"ATTENTION",
subTitle:"Username field is empty",
buttons: ['OK']
});
alert.present();
}else if(this.password.value=="") {
let alert = this.alertCtrl.create({
title:"ATTENTION",
subTitle:"Password field is empty",
buttons: ['OK']
});
alert.present();
}
else {
var headers = new Headers();
headers.append("Accept", 'application/json');
headers.append('Content-Type', 'application/json' );
let options = new RequestOptions({ headers: headers });
let data = {
username: this.username.value,
password: this.password.value
};
let loader = this.loading.create({
content: 'Processing please wait…',
});
loader.present().then(()=>{
this.http.post('http://mybusket.com/webapi/carapi/logincheck.php',data,options)
.map(res=>res.json())
.subscribe(res=>{
console.log(res)
loader.dismiss()
if(res>0) {
localStorage.setItem('response',JSON.stringify(res));
console.log(JSON.parse(localStorage.getItem('response')));
this.navCtrl.push(page)
}
else{
let alert = this.alertCtrl.create({
title:"ERROR",
subTitle:"Your Login Username or Password is invalid",
buttons: ['OK']
});
alert.present();
}
});
});
}
}
when I click the button, SignIn function runs and navigates to the menu page which is connected to welcome page.
menu.ts
export class MenuPage {
rootPage = 'Welcome';
pages = [
{ title: 'Home', component: 'Welcome' },
{ title: 'Qr Code', component: 'QrPage' },
{ title: 'Logout', component: 'LogoutPage' }
];
#ViewChild('content') nav: NavController;
constructor(public navCtrl: NavController, public navParams: NavParams)
{
}
ionViewDidLoad() {
console.log('ionViewDidLoad MenuPage');
}
openPage(page) {
// Reset the content nav to have just this page
// we wouldn't want the back button to show in this scenario
this.nav.setRoot(page.component);
}
}
I am working with lazy loading in ionic 3.
I want it so that when I log in the app, it does not require login again also when I press back button of my device app switches off.
When you login, you only save the response to your local storage. You dont have a checker if you are already logged in or not. So to stay logged in the app, you need to have a checker.
If you logged in successfully, create an item in local storage. For example, set an item isLoggedIn to true.
localStorage.setItem('isLoggedIn',true);
When you exit and re-launch the app, first thing you will do is to check the isLoggedIn from your local storage. If it is true, then navigate to the Welcome page. Otherwise, go to the Login page.
When you logout, make sure to change the isLoggedIn to false, or simply remove it.
EDIT:
Depending on your rootpage for the whole app which you can locate in your app.component.ts. (rootpage is the first page that will be shown when opening your app)
If your rootpage for the whole app is your Signin page,
your .ts file should have
constructor{
//check if the isLoggedIn in the local storage exists or is true
if(localstorage.getItem('isLoggedIn')){
// if it is true, set the menupage (which is connected to your welcome page) as root.
this.navCtrl.setRoot(MenuPage);
}
}
Additionally, in your Signin page. In your signin(page) method, adjust this
if(res>0) {
localStorage.setItem('response',JSON.stringify(res));
console.log(JSON.parse(localStorage.getItem('response')));
// add this
// set the isLoggedIn to true
localStorage.setItem('isLoggedin', true);
this.navCtrl.push(page)
}
PS> this may not work syntactically correct as I can't see your whole code. This is for your guide only, adjust the code if necessary.
We am using ionic 3 with d3js. We have lot of d3.js transitions in each component (which we believe takes lot of memory).
App responds quickly(fast) to navigation and content rendering initially however after navigating 5-10 pages, app gets slower. We see lag in page navigations and content rendering.
We believe this is because of view caching in iconic 3 (not sure if view caching is enabled in iconic 3).
When user clicks on navigation buttons, we push or pop from NavController.
Is there way to disable view caching so that app performance is same irrespective of how many times user navigates between views?
"#ionic/app-scripts": "3.1.9",
"#ionic-native/core": "4.7.0",
Sample code between home page and graph page.
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(public navCtrl: NavController) {
console.log('construct again');
}
showMigrationChart() {
this.navCtrl.push(MigrationChart);
}
showColumnChart() {
this.navCtrl.push(ColumnChart);
}
}
#Component({
selector: 'migration-chart',
templateUrl: '../../common/chart.html'
})
export class MigrationChart implements OnInit {
#ViewChild('appChart') private chartContainer: ElementRef;
public chartName = 'Column Chart';
constructor(public navCtrl: NavController) {
console.log('MigrationChart construct again');
}
ngOnInit() {
this.chartName = migrationEngine(this.chartContainer.nativeElement);
}
public onBackClick() {
console.log('getViews length= '+ this.navCtrl.length());
console.log('getViews = ', this.navCtrl.getViews());
this.navCtrl.pop();
}
}
There is no issue with Ionic framework.
On closing of page/component, there were no proper clean up of javascript timers and while loop which was causing app to slow down.
We changed code to do cleanup inside ngOnDestroy and everything work fine now.
I want message to persist through all pages of my application, and be set after the view-model and view are bounded. Every page I have a very simple template.
<template>
<h1>${message}</h1>
</template>
The code behind is empty for each page ('Page1', 'Home', 'Page2').
Here is my app.js
import {inject} from 'aurelia-framework';
export class App {
configureRouter(config, router) {
config.title = 'Pathways';
config.map([
{ route: ['','home'], name: 'home', moduleId: 'home', nav: true, title:'Home' },
{ route: 'page1', name: 'page1', moduleId: 'page1', nav: true, title:'Page1' }
]);
// Create a binding to the router object
this.router = router;
}
attached() {
this.message = this.router.currentInstruction.config.title;
}
}
The problem is, when I first load the app. ${message} is blank. Then, when I navigate to page1, the message becomes Home !! I thought that maybe the currentInstruction was lagging behind, so I added another page. Page2 if you will, but it turns out no matter what I do after the first navigation the message is always Home
So on app initialization message is blank, and then upon the first navigation message will remain Home for the entirety.
My question is, what is the "Aurelia" way to get the title of each page the user is currently on? I would think injecting the router on each page is costly
I can see two options:
The first and easiest one is using a getter property that listens to router.currentInstruction. For instance:
#computedFrom('router.currentInstruction')
get message() {
if (this.router.currentInstruction !== null)
return this.router.currentInstruction.config.title;
}
Running Example https://gist.run/?id=b01abe2859bc2bea1af0f8d21fc2045f
The second option is using the EventAggregator. For example:
attached() {
this.subscription = this.ea.subscribe('router:navigation:success', () => {
this.message = this.router.currentInstruction.config.title;
});
}
detached() {
this.subscription.dispose(); //remember to always dispose the subscription
}
Running example https://gist.run/?id=7d30d4e8d479cc209ca9013e10e91505
They say we should try to avoid the EventAggregator. So, I'd go with the first option.
You can use router.currentInstruction.config.title direct on your app.html page and it will be updated every time then router title is changed (it's using one-way binding):
<h1>title: ${router.currentInstruction.config.title}</h1>
Best way (thanks comments):
${router.currentInstruction.config.navModel.title}
I have a bizarre problem that when I change a value in the model, it does not update the view. My demo is a simple page which displays a timer whose value is updated in the model which I want reflected in the UI:
import { Component } from '#angular/core';
import { Observable } from 'rxjs/Rx';
#Component({
template: '<ion-content>Ticks (every second) : {{ticks}}</ion-content>',
})
export class ProgramOverviewPage {
ticks = 0;
ngOnInit() {
let timer = Observable.timer(0, 1000);
timer.subscribe(t => { this.ticks = t; console.log(t);});
}
}
If I set this page as my root page, it works fine. However, if I set a different page as my root page, and then immediately navigate to the timer page:
ngOnInit() {
this.nav.push(ProgramOverviewPage, {
});
}
then the page renders, but the tick value does not update the UI. I can't think of anything other than that the NavController is messing with the ChangeDetector, but I don't know why that would be. Anything I can add to debug this is much appreciated.
"ionic-angular": "2.0.0-beta.10"
Ionic 2 seems to be automatically setting Change Detection to OnPush for each of the Content objects (generated from <ion-content> I believe). This can be verified by using Augury and clicking on the Content object.
Because of this, it's necessary to explicitly tell the change detection system whenever you make any change which should be pushed to the UI using the ChangeDetectorRef.detectChanges() method. See the thoughtram blog for details.
import { Component, ChangeDetectorRef } from '#angular/core';
import { Observable } from 'rxjs/Rx';
#Component({
template: '<ion-content>Ticks (every second) : {{ticks}}</ion-content>',
})
export class ProgramOverviewPage {
ticks = 0;
ngOnInit() {
let timer = Observable.timer(0, 1000);
timer.subscribe(t => {
this.ticks = t;
console.log(t);
this.cd.detectChanges(); // Invoke the change detector
});
}
}