Ionic 3 combination tabspage and sidemenu not working - ionic-framework

i followed this article to combine sidemenu and Tabs pages.
the app.html has my menu. i have with #nav bind the ion-nav to [Content] of my ion-menu.
in my app.component.ts i have click Events. they set different Tabs pages as root and there is one normal page.
this looks like this:
#ViewChild('nav') nav: NavController;
public OnInformationClicked(): void {
this.nav.setRoot("InfoTabsPage");
}
public OnManagementClicked(): void {
this.nav.setRoot("ManagementTabsPage");
}
//some other Tabs pages
//the normal page
public OnFaqClicked(): void {
this.nav.setRoot("FaqPage");
}
in my tabs pages i'm using [selectedIndex] like this:
<ion-header>
<ion-navbar>
<ion-buttons left>
<button ion-button icon-only menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-tabs [selectedIndex]="0">
<ion-tab [root]="contactPersonRoot" tabTitle="{{tabs1Name}}" tabIcon="information-circle"></ion-tab>
<ion-tab [root]="contactSupportRoot" tabTitle="{{tabs2Name}}" tabIcon="information-circle"></ion-tab>
</ion-tabs>
but it is not working.
Problem:
when i open my menu and change the tabs pages, i can see, how the tabs changed and the right tab Icon is selected, but the Content over the tabs doesn't changed.
if i going to the normal page, this is displayed correctly. if i going to a Tabs page from the normal page, then the Tabs page is displayed correctly. if i'm trying to go back to another tabs page. it doesn't changed all content again.
i tried .... MyTabs.select(0). same issue.
i'm currently tesing with ionic serve.
"ionic-angular": "3.9.2",
"ionicons": "4.1.2",
"#angular/animations": "6.0.3",
"#angular/common": "6.0.3",
"#angular/compiler": "6.0.3",
"#angular/compiler-cli": "6.0.3",
"#angular/core": "6.0.3",
"#angular/forms": "6.0.3",
"#angular/http": "6.0.3",
"#angular/platform-browser": "6.0.3",
"#angular/platform-browser-dynamic": "6.0.3",
"#ionic-native/app-version": "^4.10.0",
"#ionic-native/background-mode": "^4.10.0",
"#ionic-native/camera": "^4.10.0",
"#ionic-native/core": "4.7.0",
"#ionic-native/in-app-browser": "^4.9.1",
"#ionic-native/network": "^4.7.0",
"#ionic-native/splash-screen": "4.7.0",
"#ionic-native/status-bar": "4.7.0",
"#ionic/storage": "^2.1.3",
anyone an idea, what's going wrong?
UPDATE
after try and error coding, changed from [selectedIndex]="0" back to myTabs.select(0) in the .ts file of the tabs page like in the article. this not working.
but i made a timeout around like so:
ionViewDidLoad() {
let _self = this;
setTimeout(function(){
_self.tabRef.select(0);
},100);
}
now i can see, the content over the tabs replaced correctly. but it looks not like a good workaround, because now i see that the old content is loading before the replacement by select.
if i open tabspage 2 now, i can see from tabspage 1 is the content behind tab 1 rendered (ionViewDidLoad, ionViewWillEnter... of tab 1 is executing). then after selecting is done, tab 1 of tabspage 2 is rendering.
UPDATE 2
app.html:
<ion-menu [content]="nav">
<ion-header>
<ion-toolbar>
<ion-title>{{menuTitle}}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<button ion-item (click)="OnInformationClicked()">
<ion-icon name="information" item-start color="primary"></ion-icon>
<ion-label>Info</ion-label>
</button>
<button ion-item (click)="OnManagementClicked()">
<ion-icon name="build" item-start color="primary"></ion-icon>
<ion-label>Manage</ion-label>
</button>
<button ion-item (click)="OnRealisationClicked()">
<ion-icon name="clipboard" item-start color="primary"></ion-icon>
<ion-label>Real</ion-label>
</button>
<button ion-item (click)="OnContactClicked()">
<ion-icon name="contact" item-start color="primary"></ion-icon>
<ion-label>Contact</ion-label>
</button>
<button ion-item (click)="OnFaqClicked()">
<ion-icon name="help" item-start color="primary"></ion-icon>
<ion-label>FAQ</ion-label>
</button>
<button ion-item (click)="OnLogoutClicked()">
<ion-icon name="log-out" item-start color="primary"></ion-icon>
<ion-label>Logout</ion-label>
</button>
</ion-list>
</ion-content>
</ion-menu>
<ion-nav [root]="rootPage" #nav [swipeBackEnabled]="false"></ion-nav>
app.component.ts
#Component({
templateUrl: 'app.html'
})
export class MyApp {
#ViewChild('nav') nav: NavController;
public menuTitle: string = GlobalHelper.GetResources().Application.Menu.Menu;
rootPage: any = HomePage;
constructor(private _css: ClientServerProvider, platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen,
private _backgroundMode: BackgroundMode, private _appProvider: AppProvider) {
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
statusBar.styleDefault();
splashScreen.hide();
_backgroundMode.enable();
});
}
public OnInformationClicked(): void {
this.nav.setRoot("InfoTabsPage");
}
public OnManagementClicked(): void {
this.nav.setRoot("ManagementTabsPage");
}
public OnRealisationClicked(): void {
this.nav.setRoot("RealisationTabsPage");
}
public OnContactClicked(): void {
this.nav.setRoot("ContactTabsPage");
}
public OnFaqClicked(): void {
this.nav.setRoot("FaqPage");
}
public OnLogoutClicked(): void {
this._css.Logout().then(loggedOut => {
if (loggedOut) {
this._appProvider.InitApplication();
}
});
}
}
for example one of the Tabs pages (the others are like this):
<ion-header>
<ion-navbar>
<ion-buttons left>
<button ion-button icon-only menuToggle>
<ion-icon name="menu"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-tabs #myTabs>
<ion-tab [root]="preparationRoot" tabTitle="{{tabs1Name}}" tabIcon="browsers"></ion-tab>
<ion-tab [root]="processRoot" tabTitle="{{tabs2Name}}" tabIcon="logo-buffer"></ion-tab>
<ion-tab [root]="complaintRoot" tabTitle="{{tabs3Name}}" tabIcon="bulb"></ion-tab>
</ion-tabs>
import { Component, ViewChild } from '#angular/core';
import { IonicPage, NavController, MenuController, Tabs } from 'ionic-angular';
import { GlobalHelper } from '../../../../helper/globalHelper';
#IonicPage()
#Component({
selector: 'page-realisation-tabs',
templateUrl: 'realisation-tabs.html'
})
export class RealisationTabsPage {
#ViewChild('myTabs') tabRef: Tabs;
preparationRoot = 'PreparationPage';
processRoot = 'ProcessPage';
complaintRoot = 'ComplaintPage';
tabs1Name = GlobalHelper.GetResources().Application.Features.Realization.Preperation_Page_Header;
tabs2Name = GlobalHelper.GetResources().Application.Features.Realization.Process_Page_Header;
tabs3Name = GlobalHelper.GetResources().Application.Features.Realization.Complaint_Page_Header;
constructor(public menuCtrl: MenuController, public navCtrl: NavController) {
}
ionViewDidLoad() {
// after OnRealisationClicked
/*
*
* with this workaround, Tabs changed, content (subpage) changed, correct * tab is active, but before the subpage changed to correct one, the previous
* subpage is loading , nearly the result of the guide in the article
let _self = this;
setTimeout(function () {
_self.tabRef.select(0);
}, 100);*/
// this is the variant of the article, without timeout
//only Tabs are changed and the correct tab Icon is active and selected
// but content (subpage) is not changed, it is still the first subpage
//of the previous tabspage
this.tabRef.select(0);
}
}
Workflow (without the timeout workaround):
after Login HomePage as root is replaced with RealisationTabsPage, Tab 1 subpage (preparation) is loaded
open Menu Click on a menu Point, which open another Tabs page, for example contacttabspage
Tabs of the contacttabspage are loaded. tab 1 of this Tabs is selected and active. but the subpage behind tab 1 of contacttabspage is still the subpage from realisationtabspage (preparation).
now i'm open menu and going to a None Tabs page (FAQ). FAQ is correctly rendered.
open menu: i'm going to a Tabs page, never mind which Tabs page (Realization, contact, info, mangement...), Tabs page rendered correctly.
now i'm going from this tabspage to another tabspage , so there is the issue again. i'm see the previous subpage of the previous tabspage.
if i'm using instead of using the select() function there is the same issue.

Made this working example of sidemenu+tabs.Hope it helps you.
https://stackblitz.com/edit/ionic-hmkkwc

I had a similar problem. Assign the pages directly to the tab variables instead of the string representation (page names) AND give the tab container unique ids. That worked for me.

Related

ionic 4 - prevent navigation on ion-back-button

Is there a way to implement the ion-back-button without having it automatically trigger nav.pop() ?
The problem stems form the funny custom arrow-back button ionic uses which I can't simply remake.
The snippet below is the closest and simplest approach but the result does not look "identical". It doesn't doesn't automatically hide when the nav stack is empty.
<ion-button slot="start" (click)="onBack()" fill="clear">
<ion-icon slot="icon-only" name="arrow-back" style="color:#424242"></ion-icon>
</ion-button>
What I would like is
<ion-back-button slot="start" (click)="someCustomLogic()"></ion-back-button>
Definitely a hack:
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button onclick="event.stopImmediatePropagation(); window.myCustomMethod()"></ion-back-button>
</ion-buttons>
<ion-title>
List
</ion-title>
</ion-toolbar>
Inside ts:
import { Component, OnInit } from '#angular/core';
import { NavController } from '#ionic/angular';
#Component({
selector: 'app-list',
templateUrl: 'list.page.html',
styleUrls: ['list.page.scss']
})
export class ListPage {
constructor( private navCtrl: NavController) {
window['myCustomMethod'] = this.overide;
}
overide = () => {
console.log("hi")
this.navCtrl.navigateBack('/home')
}
}
Why don't your try something like that :
<ion-row>
<ion-col tap="someCustomLogic()">
<ion-icon slot="icon-only" name="arrow-back" style="color:#424242"></ion-icon>
</ion-col>
</ion-row>

The push & reveal type of ion-menu does not work

I've been trying the ion-menu of Ionic 3. The "type=overlay" function works properly as the side menu overlays the screen, yet neither "push" nor "reveal" values for "type" attribute seem to be working.
When I click the button, nothing happens, but the button is sure clicked as I've checked. I have not tried them in an emulator/phone if they work. But the ionic-documents on it shows it can be tested on browser.
<ion-menu side="start" menuId="first" [content]="content" type="push">
<ion-header>
<ion-toolbar color="primary">
<ion-title>Start Menu</ion-title>
</ion-toolbar>
</ion-header>
<ion-content #content>
<ion-list>
<ion-item>Menu Item</ion-item>
<ion-item>Menu Item</ion-item>
</ion-list>
</ion-content>
</ion-menu>
<ion-header>
<ion-navbar>
<ion-title>Home</ion-title>
<ion-buttons end>
<button ion-button menuToggle (click)="openFirst()"><ion-icon name="add"></ion-icon></button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content>
content
</ion-content>
.
import { Component } from '#angular/core';
import { NavController, MenuController } from 'ionic-angular';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(public navCtrl: NavController,
private menu: MenuController) {
}
openFirst() {
this.menu.enable(true, 'first');
this.menu.open('first');
}
}
I expect this code the push the entire page and reveal the side bar menu, but it does nothing.
Button click function is not required as menuToggle is used :
<ion-header>
<ion-navbar>
<ion-title>Home</ion-title>
<ion-buttons end>
<button ion-button menuToggle ><ion-icon name="add">
</ion-icon></button>
</ion-buttons>
</ion-navbar>
</ion-header>
Also check this link.
I have implemented menu type.
https://stackblitz.com/edit/ionic-4j3yqp?file=app/app.html

Ionic 2: Menu Toogle not working

I have 2 pages, login and home, when the user successfully logins, it will be directed to the home page and I set this as the root page. I've confirmed this by using navCtrl.canGoBackFunction and it is false. I tried adding a Menu Toggle but when I pressed the toggle button the menu does not show up
This is my home.html
<ion-header>
<ion-navbar color="primary">
<button menuToogle ion-button icon-only class="menu-button-left">
<ion-icon name="menu"></ion-icon>
</button>
<ion-title class="alogo"><img alt="logo" height="35" src="../../assets/imgs/logo.png" ></ion-title>
<button ion-button class="menu-button-right" (click)="logout()">
<p>Logout</p>
</button>
</ion-navbar>
</ion-header>
<ion-content padding-left padding-right>
</ion-content>
my home.ts
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { LoginPage } from '../login/login';
import { AuthService } from '../../app/services/auth.service'
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
constructor(
public navCtrl: NavController,
private authService: AuthService
) {
}
ionViewDidLoad() {
console.log('ionViewDidLoad HomePage');
console.log(localStorage.getItem('token'));
}
logout(){
console.log('logout button clicked');
this.authService.logOut();
this.navCtrl.setRoot(LoginPage);
this.navCtrl.popToRoot();
}
}
my app.html
<ion-menu [content]="mycontent">
<ion-content>
<ion-list>
<p>List/p>
</ion-list>
</ion-content>
</ion-menu>
<ion-nav #mycontent [root]="rootPage" swipeBackEnabled="false"></ion-nav>
I've re-read multiple times the manual and I didn't see any issues with the way I did, the manual says it I put it in navbar the page should be root. I also tried using a toolbar but again clicking the menu toggle button does not do anything. Any idea ?
Persistent menus display the MenuToggle button in the Navbar on all pages in the navigation stack. To make a menu persistent set persistent to true on the element. Note that this will only affect the MenuToggle button in the Navbar attached to the Menu with persistent set to true, any other MenuToggle buttons will not be affected. In your code you have to change like below code.
my app.html
<ion-menu [content]="mycontent" persistent="true">
<ion-content>
<ion-list>
<p>List/p>
</ion-list>
</ion-content>
</ion-menu>
<ion-nav #mycontent [root]="rootPage" swipeBackEnabled="false"></ion-nav>

How may I create a dynamic nav bar with a common button and title in ionic 3?

I am developing an IONIC-3 application, whether I want a dynamic nav bar with a title and a common button. For this reason, I have created a .ts file named
commonBtn.ts. Here is the code.
import { Component } from '#angular/core';
import { NavController } from 'ionic-angular';
import { LoginPage } from '../login/login';
#Component({
selector: 'common-button',
templateUrl: 'commonBtn.html'
})
export class CommonBtnPage {
constructor(public navCtrl: NavController) { }
logOut() {
this.navCtrl.setRoot(LoginPage);
}
}
And its html is :-
<ion-header>
<ion-navbar>
<ion-title> I want to create a dynamic name </ion-title>
<ion-buttons end>
<button ion-button icon-only (click)="logOut()">
<ion-icon name="log-out"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
Now, my question is that, How may I change the title name dynamically means when user come into "Home Page", title will be "Home" or user come into "About" page, title will be "About".
We can manage this in ionic v1 via $rootScope but here in Ionic v3, how can I resolve this ?
Also I am giving the html of Home page
<ion-header>
<ion-navbar>
<ion-title>Home</ion-title>
<common-button></common-button>
</ion-navbar>
</ion-header>
<ion-content padding>
<button ion-button (click) = 'clickHere()'> Click </button>
</ion-content>
Please suggest me what to do.
Generally, you need to use Input decorator. Check Component Interactions.
In CommonBtnPage,
import { Component,Input } from '#angular/core';
import { NavController } from 'ionic-angular';
import { LoginPage } from '../login/login';
#Component({
selector: 'common-button',
templateUrl: 'commonBtn.html'
})
export class CommonBtnPage {
#Input()title:string;//here
constructor(public navCtrl: NavController) { }
logOut() {
this.navCtrl.setRoot(LoginPage);
}
}
In the html, set the title,
<ion-header>
<ion-navbar>
<ion-title>{{title}}</ion-title>
<ion-buttons end>
<button ion-button icon-only (click)="logOut()">
<ion-icon name="log-out"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
You can set the component and send the title as:
<common-button [title]="'home'"></common-button>

How to extract and reuse nav bar template and logic in Ionic 2 app?

Having had some experience with Angular 1.x (but not Ionic 1.x), I am now trying to develop a small mobile app using Ionic 2, which is based on Angular 2.
I am familiar with URL-based routing principles such as those used in ui-router. The concept in Ionic 2 is different and is based on pushing/popping pages on top of a root page.
So far I have managed to create 2 pages (Search and Person) with a nav bar on top, and to navigate from one to the other, and back. The navbar has a button to return to the root (Search) page (because later it will be possible to navigate from a person to other pages, further away from the root page).
However I could not figure out how to extract the navbar and navbar controller in a separate file. So the markup and the button handler (goToSearch) are repeated in every page.
How can I extract the navbar template and logic so as not to repeat it ?
Bonus question (and strongly related) : Can someone explain the difference between the ion-nav in app.html and the ion-navbar in the pages ?
app.ts :
import 'es6-shim';
import {App, Platform} from 'ionic-angular';
import {StatusBar} from 'ionic-native';
import {TabsPage} from './pages/tabs/tabs';
import {Search} from './pages/search/search'
#App({
templateUrl: 'build/pages/app.html',
config: {} // http://ionicframework.com/docs/v2/api/config/Config/
})
export class MyApp {
rootPage: any = Search;
constructor(platform: Platform) {
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
StatusBar.styleDefault();
});
}
}
app.html :
<ion-nav [root]="rootPage">
<ion-buttons end>
<button>
<ion-icon name="search"></ion-icon>
</button>
</ion-buttons>
</ion-nav>
search.ts :
import {Page} from 'ionic-angular';
import {Nav} from 'ionic-angular';
import {Person} from '../person/person'
#Page({
templateUrl: 'build/pages/search/search.html',
})
export class Search {
nav:Nav;
constructor(nav:Nav) {
this.nav = nav;
}
goToPerson() {
this.nav.push(Person);
}
}
search.html:
<ion-navbar *navbar>
<ion-title>Search</ion-title>
<ion-buttons end>
<button>
<ion-icon name="search"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
<ion-content padding class="page1">
<h2>Welcome to SEARCH</h2>
<button (click)="goToPerson()">Go to person</button>
</ion-content>
person.ts :
import {Page} from 'ionic-angular';
import {Nav} from 'ionic-angular';
import {Search} from '../search/search'
#Page({
templateUrl: 'build/pages/person/person.html',
})
export class Person {
nav:Nav;
constructor(nav:Nav) {
this.nav = nav;
}
goToSearch() {
this.nav.push(Search);
}
}
person.html :
<ion-navbar *navbar>
<ion-title>Person</ion-title>
<ion-buttons end>
<button (click)="goToSearch()">
<ion-icon name="search"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
<ion-content padding class="page1">
<h2>Welcome to PERSON</h2>
<button (click)="goToSearch()">Go to search</button>
</ion-content>
you could create a component to hold your header config, components are reusable and can be very dynamic, just dont forget to import it on your module
default-header.html
<ion-navbar *navbar>
<ion-title>{{pageTitle}}</ion-title>
<ion-buttons end>
<button (click)="goToSearch()">
<ion-icon name="{{icon}}"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
default-header.ts
import { Component, Input, Inject, ViewChild } from "#angular/core";
import { Content } from "ionic-angular";
import { NavController } from "ionic-angular/navigation/nav-controller";
import {Person} from '../person/person'
#Component({
selector: "default-header",
templateUrl: "default-header.html"
})
export class DefaultHeaderComponent {
#Input() pageTitle: any;
#Input() icon= true;
#ViewChild(Content) content: Content;
constructor(
public navCtrl: NavController,
) {
console.log("Hello DefaultHeaderComponent Component");
}
ionViewDidLoad() {
const self = this;
}
gotNotificationsPage() {
this.global.setRoot("NotificationsPage");
}
}
and call it in the place of your navbar like this in any page
<default-header [title]="'Person'" [icon]="'search'"></default-header>