Ionic/MobileFirst app automatically redirecting page - ionic2

I have a following flow in my Ionic 3 app which is powered with MobileFirst Platform V8:
WelcomePage --> HomePage --> ViewReportPage
When user opens a app he will land on WelcomePage where he enters his credentials. Once a credentials are validated then he will be taken to HomePage from where he will click View button to go to ViewReportPage.
In the ViewReportPage user clicks the search button to search the reports.
My problem is, when user clicks the search button then as soon as the service code sends the request to fetch the data from the server, I am getting redirected to HomePage. Don't know whats the problem is. Below is the code.
Strange thing is, this is only happening if I close the app and opens it and then follow the steps given above. If I go ViewReportPage after being redirected to HomePage and then click search button then I am not facing this issue and the app is working as it should.
ViewReportPage HTML
<ion-card>
<ion-list no-lines>
<ion-item>
<ion-label>Year</ion-label>
<ion-select [(ngModel)]="year">
<ion-option value="{{yearToSearch}}" *ngFor="let yearToSearch of years">{{yearToSearch}}</ion-option>
</ion-select>
</ion-item>
<ion-item>
<button round center padding class="align-center" color="secondary" ion-button (click)="search()">
<ion-icon ios="ios-search" md="md-search" class="ion-lable-icon-padding"></ion-icon>
Search
</button>
</ion-item>
</ion-list>
</ion-card>
ViewReport TS
#IonicPage()
#Component({
selector: 'page-view-report',
templateUrl: 'view-report.html',
})
export class ViewReportPage {
public years : number[] = null;
public year = null;
public corrData : any[] = null;
constructor(public navCtrl: NavController,
public navParams: NavParams,
public loginSrvc : LoginService,
public corrSrvc : ReportService,
public events: Events) {
let currentYear = new Date().getFullYear();
this.year = currentYear;
this.years = [
currentYear,
currentYear -1 ,
currentYear - 2
];
this.events.subscribe('corrResults',(value)=>{
this.corrData = this.corrSrvc.getReportData();
});
}
ionViewDidLoad() {
console.log('Hello ViewReportPage Page');
}
search(){
let searchData : ReportSearchModel = new ReportSearchModel(
this.loginSrvc.getUserId(),
this.loginSrvc.getEncodedSignature(),
this.year,
null
);
let invocationData = {
procedure : 'getReports',
parameters : searchData,
navController : this.navCtrl
};
this.corrSrvc.search(invocationData);
}
}
ReportService TS
search(invocationData){
let procedureName = invocationData.procedure;
let parameters = invocationData.parameters;
let nav : NavController = invocationData.navController;
this.nav = nav;
let isuserLoggedIn = this.loginService.checkForLoggedInUser();
this.ngZone.run(
() => {
let reqToSend = new WLResourceRequest('/adapters/MyMFPAdapter'+procedureName, WLResourceRequest.GET);
let jsonToStingData = JSON.stringify(parameters);
reqToSend.setQueryParameter("params", `[${jsonToStingData}]`);
reqToSend.send().then((response) => {
let invocationResponse = response.responseJSON;
//resolve(response.responseJSON);
console.log(invocationResponse);
this.corrData = invocationResponse['reportBeans'];
if(this.corrData == null || this.corrData == undefined || this.corrData.length < 1){
alert('No Report Found');
}
this.events.publish('corrResults','results');
});
}
);
}
getCorrespondenceData(){
return this.corrData;
}

Related

Getting credit card brand and show error message when using hosted fields in Braintree

I am trying to create payment page using braintree's hosted fields.
I have created sandbox account.
But i am not getting additional details like Card brand, error message like Drop in UI.
How to get those functionalities using Hosted fields.
import React from 'react';
var braintree = require('braintree-web');
class BillingComponent extends React.Component {
constructor(props) {
super(props);
this.clientDidCreate = this.clientDidCreate.bind(this);
this.hostedFieldsDidCreate = this.hostedFieldsDidCreate.bind(this);
this.submitHandler = this.submitHandler.bind(this);
this.showPaymentPage = this.showPaymentPage.bind(this);
this.state = {
hostedFields: null,
errorOccurred: false,
};
}
componentDidCatch(error, info) {
this.setState({errorOccurred: true});
}
componentDidMount() {
this.showPaymentPage();
}
showPaymentPage() {
braintree.client.create({
authorization: 'sandbox_xxxxx_xxxxxxx'
}, this.clientDidCreate);
}
clientDidCreate(err, client) {
braintree.hostedFields.create({
onFieldEvent: function (event) {console.log(JSON.stringify(event))},
client: client,
styles: {
'input': {
'font-size': '16pt',
'color': '#020202'
},
'.number': {
'font-family': 'monospace'
},
'.valid': {
'color': 'green'
}
},
fields: {
number: {
selector: '#card-number',
'card-brand-id': true,
supportedCardBrands: 'visa'
},
cvv: {
selector: '#cvv',
type: 'password'
},
expirationDate: {
selector: '#expiration-date',
prefill: "12/21"
}
}
}, this.hostedFieldsDidCreate);
}
hostedFieldsDidCreate(err, hostedFields) {
let submitBtn = document.getElementById('my-submit');
this.setState({hostedFields: hostedFields});
submitBtn.addEventListener('click', this.submitHandler);
submitBtn.removeAttribute('disabled');
}
submitHandler(event) {
let submitBtn = document.getElementById('my-submit');
event.preventDefault();
submitBtn.setAttribute('disabled', 'disabled');
this.state.hostedFields.tokenize(
function (err, payload) {
if (err) {
submitBtn.removeAttribute('disabled');
console.error(err);
}
else {
let form = document.getElementById('my-sample-form');
form['payment_method_nonce'].value = payload.nonce;
alert(payload.nonce);
// form.submit();
}
});
}
render() {
return (
<div className="user-prelogin">
<div className="row gutter-reset">
<div className="col">
<div className="prelogin-container">
<form action="/" id="my-sample-form">
<input type="hidden" name="payment_method_nonce"/>
<label htmlFor="card-number">Card Number</label>
<div className="form-control" id="card-number"></div>
<label htmlFor="cvv">CVV</label>
<div className="form-control" id="cvv"></div>
<label htmlFor="expiration-date">Expiration Date</label>
<div className="form-control" id="expiration-date"></div>
<input id="my-submit" type="submit" value="Pay" disabled/>
</form>
</div>
</div>
</div>
</div>
);
}
}
export default BillingComponent;
I am able to get basic functionalities like getting nonce from card details. But i am unable to display card brand image/error message in the page as we show in Drop in UI.
How to show card brand image and error message using hosted fields?
Page created using Hosted fields:
Page created Drop in UI - Which shows error message
Page created Drop in UI - Which shows card brand
Though we do not get exact UI like Drop in UI, we can get the card type and display it ourselves by using listeners on cardTypeChange.
hostedFieldsDidCreate(err, hostedFields) {
this.setState({hostedFields: hostedFields});
if (hostedFields !== undefined) {
hostedFields.on('cardTypeChange', this.cardTypeProcessor);
hostedFields.on('validityChange', this.cardValidator);
}
this.setState({load: false});
}
cardTypeProcessor(event) {
if (event.cards.length === 1) {
const cardType = event.cards[0].type;
this.setState({cardType: cardType});
} else {
this.setState({cardType: null});
}
}
cardValidator(event) {
const fieldName = event.emittedBy;
let field = event.fields[fieldName];
let validCard = this.state.validCard;
// Remove any previously applied error or warning classes
$(field.container).removeClass('is-valid');
$(field.container).removeClass('is-invalid');
if (field.isValid) {
validCard[fieldName] = true;
$(field.container).addClass('is-valid');
} else if (field.isPotentiallyValid) {
// skip adding classes if the field is
// not valid, but is potentially valid
} else {
$(field.container).addClass('is-invalid');
validCard[fieldName] = false;
}
this.setState({validCard: validCard});
}
Got the following response from braintree support team.
Hosted fields styling can be found in our developer documentation. Regarding the logos, you can download them from the card types official websites -
Mastercard
Visa
AMEX
Discover
JCB
Or online from other vendors.
Note: Drop-In UI will automatically fetch the brand logos and provide validation errors unlike hosted fields as it is less customizable.

How to hide native android keyboard in IONIC 2 when clicking on a text box?

How to hide native android keyboard when clicking on text box using IONIC 2? I have installed IONIC keyboard plugin from https://ionicframework.com/docs/native/keyboard/ link and uses this.keyboard.close();
But still keyboard is opening. Help me how to close the keyboard. I am basically showing DOB from the datepicker plugin in a TEXTBOXenter image description here.
This is the ts file(datepicker1.ts)
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { DatePicker } from '#ionic-native/date-picker';
import { Keyboard } from '#ionic-native/keyboard';
#IonicPage()
#Component({
selector: 'page-datepicker1',
templateUrl: 'datepicker1.html',
})
export class Datepicker1Page {
public today:any;
constructor(public navCtrl: NavController, public navParams: NavParams,private datePicker: DatePicker,private keyboard: Keyboard) {
}
ionViewDidLoad() {
console.log('ionViewDidLoad Datepicker1Page');
}
openDatepicker()
{
this.keyboard.close();
this.datePicker.show({
date: new Date(),
mode: 'date',
androidTheme: this.datePicker.ANDROID_THEMES.THEME_DEVICE_DEFAULT_LIGHT
}).then(
date => {
this.today=date.getDate()+'/'+date.getMonth()+'/'+date.getFullYear()},
err => console.log('Error occurred while getting date: ', err)
);
}
}
And this is the datepicker1.html page
<ion-header>
<ion-navbar>
<ion-title>datepicker page</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-item>
<ion-label>DOB</ion-label>
<ion-input type="text" name="DOB" (click)="openDatepicker()" [(ngModel)]="today" ng-readonly></ion-input>
</ion-item>
</ion-content>
You have missed to declare the today variable in the class and you missed to add disabled="true" in ion-input tag. Everything is working fine and I have tested it.
TS File
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { Keyboard } from '#ionic-native/keyboard';
import { DatePicker } from '#ionic-native/date-picker';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(public navCtrl: NavController, public keyboard : Keyboard, public datePicker : DatePicker) {
}
today : any;
openDatepicker(){
this.keyboard.close();
this.datePicker.show({
date: new Date(),
mode: 'date',
androidTheme: this.datePicker.ANDROID_THEMES.THEME_DEVICE_DEFAULT_LIGHT
}).then(
date => {
this.today=date.getDate()+'/'+date.getMonth()+'/'+date.getFullYear()},
err => console.log('Error occurred while getting date: ', err)
);
}
}
HTML File
<ion-header>
<ion-navbar>
<ion-title>
Ionic Blank
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-item>
<ion-label>DOB</ion-label>
<ion-input disabled="true" type="text" name="DOB" (click)="openDatepicker()" [(ngModel)]="today" ng-readonly></ion-input>
</ion-item>
</ion-content>
1) import { DatePicker } from '#ionic-native/date-picker/ngx'; in app.module.ts and keyboard.page.ts
2) public keyboard : Keyboard, in your constructor inject
3) https://ionicframework.com/docs/native/keyboard Take reference from this Official site
openDatepickerStart(){
setTimeout(() => {
this.keyboard.hide();
}, 100);
this.datePicker.show({
date: new Date(),
mode: 'date',
androidTheme: this.datePicker.ANDROID_THEMES.THEME_DEVICE_DEFAULT_LIGHT
}).then(
date => {
this.SelectDateModelDetails.get('StartTime').patchValue(date.getDate()+'/'+date.getMonth()+'/'+date.getFullYear())},
err => console.log('Error occurred while getting date: ', err)
);
}

Ionic2 NativeStorage can't getItem(user)

I have an ionic 2 app and am using native FB Login to retrieve name/pic and saving it to NativeStorage. The flow is that I open WelcomePage, log in, and save the data. From there, navPush to HomePage. So far it works great.
However, I have a ProfilePage (accessible via tabRoot), the fails. The reason is that in my profile.html I have the following tag that should render Username (this works on HomePage, but not on ProfilePage):
{{ user.name }}
The error I get on XCode is:
2017-05-02 18:40:41.657374 FoxBox App[1102:226159] ERROR: Failed to navigate: undefined is not an object (evaluating 'co.user.picture')
Note that for some reason it prepends it with 'co.' which I have no idea where its coming from or what it means.
Here is the WelcomePage code:
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { HomePage } from '../home/home';
import { AboutPage } from '../about/about';
import { Facebook, NativeStorage } from 'ionic-native';
//import { FacebookAuth, User, Auth } from '#ionic/cloud-angular';
import { CloudSettings, CloudModule } from '#ionic/cloud-angular';
import {GoogleAnalytics} from 'ionic-native';
#Component({
selector: 'page-welcome',
templateUrl: 'welcome.html'
})
export class WelcomePage {
FB_APP_ID: number = 1234567890;
homePage = HomePage;
aboutPage = AboutPage;
constructor(
public navCtrl: NavController,
//public facebookAuth: FacebookAuth,
//public auth: Auth,
//public user: User,
) {
Facebook.browserInit(this.FB_APP_ID, "v2.8");
}
doFbLogin(){
//alert("fb is logged in");
let permissions = new Array();
let nav = this.navCtrl;
//the permissions your facebook app needs from the user
permissions = ["public_profile"];
Facebook.login(permissions)
.then(function(response){
let userId = response.authResponse.userID;
let params = new Array();
//Getting name and gender properties
Facebook.api("/me?fields=name,gender", params)
.then(function(user) {
user.picture = "https://graph.facebook.com/" + userId + "/picture?type=large";
//now we have the users info, let's save it in the NativeStorage
NativeStorage.setItem('user',
{
name: user.name,
gender: user.gender,
picture: user.picture,
email: user.email,
})
.then(function(){
nav.push(HomePage);
console.log("User Data Stored");
}, function (error) {
console.log(error);
})
})
}, function(error){
console.log(error);
});
}
}
Here is the HomePage code:
import { Component } from '#angular/core';
import { NavController, Platform } from 'ionic-angular';
import { Http } from '#angular/http';
import 'rxjs/add/operator/map';
import { ClaimPage } from '../claim/claim';
import { SocialSharing } from '#ionic-native/social-sharing';
import { Facebook, NativeStorage } from 'ionic-native';
//import { FacebookAuth, User, Auth } from '#ionic/cloud-angular';
import { CloudSettings, CloudModule } from '#ionic/cloud-angular';
import {GoogleAnalytics} from 'ionic-native';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
posts: any;
sendme: any;
claimPage = ClaimPage;
user: any;
userReady: boolean = false;
constructor(
public navCtrl: NavController,
public http: Http,
private sharingVar: SocialSharing,
public platform: Platform,
) {
// Check to see if user already exists (via FB login)
let env = this;
NativeStorage.getItem('user')
.then(function (data){
env.user = {
name: data.name,
gender: data.gender,
picture: data.picture
};
env.userReady = true;
// console.log(data.name);
}, function(error){
console.log(error);
});
this.platform.ready().then(() => {
//alert("platform is ready");
GoogleAnalytics.trackView("Home-Page", "http://foxboxapp.com/home", true);
//alert("GA called");
});
this.http.get('http://getyourtryston.com/foox/sample.php').map(res => res.json()).subscribe(data => {
this.posts = data.data.children;
});
}
otherShare(){
this.sharingVar.share("FoxBox App","Get Awesome College Deals",null/*File*/,"http://fooxsocial.com")
.then(()=>{
//alert("Success");
},
()=>{
alert("Sharing Failed!")
})
}
}
And here is the ProfilePage code which fails:
import { Component } from '#angular/core';
import { NavController, Platform } from 'ionic-angular';
import { WelcomePage } from '../welcome/welcome';
import {GoogleAnalytics} from 'ionic-native';
import { SocialSharing } from '#ionic-native/social-sharing';
import { Facebook, NativeStorage } from 'ionic-native';
//import { FacebookAuth, User, Auth } from '#ionic/cloud-angular';
//import { CloudSettings, CloudModule } from '#ionic/cloud-angular';
#Component({
selector: 'page-about',
templateUrl: 'about.html'
})
export class AboutPage {
user: any;
userReady: boolean = false;
constructor(
public navCtrl: NavController,
public platform: Platform,
private sharingVar: SocialSharing,
//public facebookAuth:FacebookAuth,
//public auth:Auth,
) {
// Check to see if user already exists (via FB login)
let env = this;
NativeStorage.getItem('user')
.then(function (data){
env.user = {
name: data.name,
gender: data.gender,
picture: data.picture
};
env.userReady = true;
// console.log(data.name);
}, function(error){
console.log(error);
});
// PLATFORM READY, do your thang!
this.platform.ready().then(() => {
// Ping Google Analytics
GoogleAnalytics.trackView("Profile Page", "http://foxboxapp.com/home", true);
});
}
otherShare(){
this.sharingVar.share("FOOX Social App","Get Awesome College Deals",null/*File*/,"http://fooxsocial.com")
.then(()=>{
//alert("Success");
},
()=>{
alert("Sharing Failed!")
})
}
doFbLogout(){
var nav = this.navCtrl;
Facebook.logout()
.then(function(response) {
//user logged out so we will remove him from the NativeStorage
NativeStorage.remove('user');
nav.push(WelcomePage);
}, function(error){
console.log(error);
});
}
}
And here is ProfilePage.html
<ion-header>
<ion-navbar color="light" hideBackButton="true">
<ion-buttons end>
<button ion-button icon-only (click)="otherShare()">
<ion-icon name="share"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content>
<ion-card class="pCard">
<div class="pHeader" align="center">
<div *ngIf="user" class="pImgBox" align="center">
<img class="pImage" src="{{ user.picture }}">
</div>
<div class="pUsername" align="center">
<div *ngIf="user"> {{user.name}} </div>
<br>
<span class="pSchool">(Santa Monica College)</span>
</div>
</div>
<ion-list>
<ion-item class="pItems">
Share App
</ion-item>
<ion-item class="pItems">
Give Us Feedback
</ion-item>
<ion-item class="pItems">
Suggest Vendors
</ion-item>
<ion-item class="pItems">
Privacy & Terms of Service
</ion-item>
<ion-item class="pItems">
Log Out
</ion-item>
<ion-item class="pItems">
Delete Account
</ion-item>
</ion-list>
</ion-card>
<button ion-button round (click)="doFbLogout()">Log Out</button>
</ion-content>
I should mention that, if I remove {{ user.name }} and {{ user.picture }} from my ProfilePage.html, there does NOT seem to be any problems. In fact, if you notice in the ts of ProfilePage, I can both Alert and Console.log the username (data.name) without any issues.
I'm a beginner and would appreciate any concise help in this regard. Thank you.
I finally found a solution. In the html file (ProfilePage.html), I used an *ngIf conditional:
<div *ngIf="user"> {{user.name}} </div>
This will introduce a delay such that the 'user' object is no longer null as it reads from NativeStorage.
Alternatively, an Elvis Operator also works for me:
<div> {{ user?.name }} </div>

Ionic 2 - List update doesn't reflect in UI unless page is refreshed

My template:
<ion-item-sliding *ngFor="let draft of drafts">
<ion-item>
<h2>Report draft header</h2>
</ion-item>
<ion-item-options side="left">
<button ion-button color="secondary" (click)="draftUpload(draft.report.pk)">
<ion-icon name="md-cloud-upload"></ion-icon>
Upload
</button>
</ion-item-options>
</ion-item-sliding>
In the controller, I do this:
draftUpload(pk) {
this.dataService.uploadReport(pk);
this.drafts = this.dataService.getDraftReports();
}
Here is the getDraftReports() functions:
getDraftReports() {
var draftReports = [];
let reportObj : any;
this.storage.forEach((value, key, index) => {
reportObj = JSON.parse(value);
if(reportObj.report.uploaded=="no"){
draftReports.push(reportObj);
}
});
return draftReports;
}
This doesn't work, although the DB changes are made. If I refresh the page, or navigate away and back, the list updates.
What am I doing wrong?
It seems a change detection issue. Change detection is fired on every browser event, timeout or http request.
The case is that your function: getDraftReports() is asyncronous and is its callback is not detected for Angular and consequently it doesn't fires the change detection event in order to update the view.
In order to solve this you will have to wrap this function into the angular zone. See this code:
import zone:
import { NgZone } from '#angular/core';
Inject the service ngZone:
constructor(private zone: NgZone) {
....
}
And finally add this to your function:
draftUpload(pk) {
this.dataService.uploadReport(pk);
this.zone.run(
() => {
this.drafts = this.dataService.getDraftReports();
}
)
}
Hope this helps.
this.storage.foreach returns a promise and hence is asynchronous.
Your draftReports array is returned before it is set.You need to return the promise :
getDraftReports(draftsHandler:any) {
//var draftReports = [];
//Use a filter method and return the promise.
return this.storage.forEach((value, key, index) => {
let reportObj : any;
reportObj = JSON.parse(value);
if(reportObj.report.uploaded=="no"){
//draftReports.push(reportObj);
draftsHandler(reportObj);
}
});
}
In your draftUpload set drafts within then.
draftUpload(pk) {
this.dataService.uploadReport(pk);
this.dataService.getDraftReports((data)=>this.draftsHandler(data)).then(()=>{
//next steps
}
}
draftsHandler(data:any){
this.drafts.push(data)
}

Changing tabs dynamically in Ionic 2

I am creating an Ionic application where I am using tabs. I want to be able to navigate from one tab to the other using the typescript component class attached to the tab template. For example, Tab 2 should be activated upon triggering an event in tab 1.
My tab loads well in the tabs and all is well as long as I manually click on the tab to move around, but trying to switch context in the code behind as been very tricky.
At load time I am able to make any one of the tabs active by simply setting the [selectedIndex] attribute of the ion-tabs to the value of an attribute in my tabs component class.
Tabs Parent Template - tab.html
<ion-tabs #tabParent [selectedIndex]="tabToShow">
<ion-tab tabTitle="Tab 1" [root]="tab2" [rootParams]="{parent : tabParent}"></ion-tab>
<ion-tab tabTitle="Tab 2" [root]="tab2" [rootParams]="{parent : tabParent}></ion-tab>
<ion-tab tabTitle="Tab 3" [root]="tab3" [rootParams]="{parent : tabParent}></ion-tab>
</ion-tabs>
Component - tab.ts
import {Page} from 'ionic-angular';
import {Tab1} from '../tab1/tab1.ts';
import {Tab2} from '../tab2/tab2.ts';
import {Tab3} from '../tab3/tab3.ts';
#Page({
templateUrl : 'build/pages/tab/tab.html'
})
export class Tab{
tab1: any;
tab2: any;
tab3: any;
tabToShow : number = 1;
ngOnInit(){
this.tab1 = Tab1;
this.tab2 = Tab2;
this.tab3 = Tab3;
}
}
In the component for the first tab (Tab1), i am able to get a reference to the parent tabs by using [rootParams] = "{parent : tabParent}" and I am able access all available properties exposed by the tabs object. An event generated on the tab1.html template, causes the goToTab2() to be called. So, I was able to set SelectedIndex to 1 (which I expect to change the active tab to the second tab). But the tab is not changing.
tab1.ts
import {Page, NavParams} from 'ionic-angular';
import {Tab2} from '../tab/tab2/tab2.ts'
#Page({
templateUrl : 'build/pages/tab/tab1/tab1.html'
})
export class Tab1{
parent : any;
constructor(nav : NavParams){
this.parent = nav.data;
}
goToTab2(event, value): void{
this.parent.parent.selectedIndex = 1;
console.log(this.parent.parent);
}
}
I need help, what am I doing wrong?
I had the same problem and after hours of trying and debugging, it turned out to be so simple:
import {Page, NavController, Tabs} from 'ionic-angular';
#Page({
templateUrl : 'build/pages/tab/tab1/tab1.html'
})
export class Tab1{
constructor(private nav: NavController) {
};
selectTab(index: number) {
var t: Tabs = this.nav.parent;
t.select(index);
}
}
this.nav.parent.select(tabIndex);
tabIndex starts from 0
I wanted to navigate to tabbed pages from a side menu. To enable that I did the following:
Tabs.html:
<ion-tabs selectedIndex="{{activeTab}}">
<ion-tab [root]="tab1Root" tabTitle="Home" tabIcon="home"></ion-tab>
<ion-tab [root]="tab2Root" tabTitle="Profiles" tabIcon="filing"> </ion-tab>
</ion-tabs>
Tabs.ts
...normal stuff preceding ...
export class TabsPage {
#ViewChild('page-tabs') tabRef: Tabs;
activeTab: any;
tab1Root: any = HomePage;
tab2Root: any = ProfilesPage;
constructor(public navCtrl: NavController, public params: NavParams) {
this.authUser = params.get("authUser");
this.activeTab = params.get("tab")?params.get("tab"):0;
}
}
Then I just passed the tab parameter from app.component.ts
...normal stuff preceding ...
export class MyApp {
#ViewChild(Nav) nav: Nav;
isAppInitialized: boolean = false;
rootPage: any
pages: Array<{title: string, type: string, index?: number, component?: any}>;
constructor(
private platform: Platform,
public menu: MenuController) {
}
ngOnInit() {
this.platform.ready().then(() => {
this.pages = [
{title: 'Home', type: 'tab', index: 0},
{title: 'Profiles', type: 'tab', index:1},
{title: 'Create Shares', type: 'page', component: HomePage},
{title: 'Existing Shares',type: 'page', component: ProfilesPage}
];
});
}
openPage(page) {
this.menu.close();
if (page.type==='tab') {
this.nav.setRoot(TabsPage,{tab: page.index});
} else {
this.nav.setRoot(page.componenet);
}
}
}
Then in app.html
<ion-header>
<ion-toolbar>
<ion-title>Left Menu</ion-title>
<button class="absolute-right" ion-button clear menuClose="left">
<span ion-text showWhen="ios">Close</span>
<ion-icon name="md-close" showWhen="android,windows"></ion-icon>
</button>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<button ion-item *ngFor="let p of pages" (click)="openPage(p)">
{{p.title}}
</button>
</ion-list>
</ion-content>
</ion-menu>
There you have it...
For Ionic 3+, you don't have access to this.nav, so you can use a function such as:
go(tabIndex: number)
{
this.app.getActiveNavs()[0].parent.select(tabIndex);
}
If the function is defined in a common class (imported in all your pages), you can then call it wherever you want:
<button ion-button (click)="core.go(0);">Go to first tab (#0)</button>
<button ion-button (click)="core.go(1);">Go to second tab (#1)</button>
Even easier now! You can add the selectedIndex attribute to
<ion-tabs selectedIndex="2">
<ion-tab [root]="tab1Root"></ion-tab>
<ion-tab [root]="tab2Root"></ion-tab>
<ion-tab [root]="tab3Root"></ion-tab>
</ion-tabs>
export class Page1 {
tab:Tabs;
// create a class variable to store the reference of the tabs
constructor(public navCtrl: NavController, private nav: Nav) {
this.tab = this.navCtrl.parent;
/*Since Tabs are declarative component of the NavController
- it is accessible from within a child component.
this.tab - actually stores an array of all the tabs defined
in the tab.html / tab component.
*/
}
goToTab2 (){
this.tab.select(1);
// the above line is self explanatory. We are just calling the select() method of the tab
}
goToTab3 (){
this.tab.select(2);
}
}
In your tab1 component (tab1.ts),try to inject the parent component Tab :
export class Tab1{
constructor(#Host() _parent:Tab) {}
goToTab2(event, value): void{
this._parent.tabToShow = 1 ;
}
}
You can get tabs element by using #ViewChild or IonicApp.getComponent().
The tab-button can be accessed by going through tabs element.
The tab-button click event is bound to onClick function by using #HostListener.
You can switch tab by calling the tab-button onClick button.
export class TabsPage {
tab1TabRoot: Type = Tab1Page;
tab2TabRoot: Type = Tab2Page;
tab3TabRoot: Type = Tab3Page
#ViewChild(Tabs) tabs;
constructor(
private _ngZone: NgZone,
private _platform: Platform,
private _app: IonicApp,
) {
}
ngOnInit() {
}
ngAfterViewInit() {
console.log(this.tabs);
}
public selectTab2() {
this._ngZone.run(function() {
tabs._btns._results[0].onClick();
});
}
}
Its simple just use NavController class and its property .parent.select(position of tab you want)
constructor(public navCtrl: NavController) {
}
goToTab2(){
this.navCtrl.parent.select(1);
}