Ionic: No back button when navigating away from tab view - angularjs

I cannot figure out how to get the back button to show when navigating away from a tabbed view to a single page view. The single page view shouldn't have the tab bar. I can make the back button appear when I make the view I'm navigating to part of the tab hierarchy, but that's not what I want.
I've been looking around and can't seem to find a post on this issue. I just might not be searching for the right keywords.
My set up is this...
tabs: tab.feed, tab.friends, tab.account
other view: randompage
Here is my route set up...
.state('randompage', {
url:'/randompage',
templateUrl: 'templates/randompage.html',
controller: 'RandomPageCtrl'
})
.state('tab', {
url: '/tab',
abstract: true,
templateUrl: 'templates/tabs.html',
controller: 'TabCtrl'
})
.state('tab.feed', {
url: '/feed',
views: {
'tab-feed': {
templateUrl: 'templates/tab-feed.html',
controller: 'FeedCtrl'
}
}
})
Here is the tabs.html
<ion-tabs class="tabs-icon-top tabs-top">
<!-- Feed Tab -->
<ion-tab title="Feed" icon="icon ion-ios7-paper" href="#/tab/feed">
<ion-nav-view name="tab-feed"></ion-nav-view>
</ion-tab>
<!-- The rest are just from the tab skeleton -->
<ion-tab title="Friends" icon="icon ion-heart" href="#/tab/friends">
<ion-nav-view name="tab-friends"></ion-nav-view>
</ion-tab>
<ion-tab title="Account" icon="icon ion-gear-b" href="#/tab/account">
<ion-nav-view name="tab-account"></ion-nav-view>
</ion-tab>
</ion-tabs>
Here is the tab-feed.html
<ion-view title="Feed">
<ion-nav-buttons side="right">
<a class="button button-icon ion-android-camera" href="#/randompage"></a>
</ion-nav-buttons>
<ion-content class="padding">
<h1>Feed</h1>
</ion-content>
</ion-view>
Here is the randompage.html
<ion-view title="Random Page">
<ion-content lass="padding">
</ion-content>
</ion-view>
Everything navigates and shows correctly except the back button is not showing.
Please let me know if you know of any alternate solution, possibly what I may be doing wrong, or need more information.
Thanks!

This has been a long time problem for me as well. While the history stack is broken in this use case, 'backView' in the history object is correct. The full history object can be seen with this log line:
console.log( JSON.stringify($ionicHistory.viewHistory(), null, 4) );
My solution is to manually add in a Back button on global pages.
Global page html:
<ion-view view-title="Help">
<ion-nav-buttons side="left">
<button class="button button-clear" ng-click="goBack()"><i class="icon ion-arrow-left-c" ></i> Back</button>
</ion-nav-buttons>
Javascript:
$scope.goBack = function() {
$ionicHistory.goBack();
};
Another alternative is to modify the ionic source. Replace enabledBack() in ionic.bundle.js with this:
enabledBack: function(view) {
//original code
//var backView = getBackView(view);
//return !!(backView && backView.historyId === view.historyId);
//new code to show back
var backView = viewHistory.backView;
return backView != null;
},

I have the same issue. By check the source code, ionic sets up an default history stack named root history, views are pushed and popped from the stack as user navigate through the app. However, the tab view is taken out of this default history stack and a new stack will be setup for it.
splash view --> tab view --> random page (out of tab)
|
tab1 --> nested view (in tab)
|
tab2 --> nested view (in tab)
root history stack:
splash view ---> random page
tab history stack:
tab view ---> tab1 --> nested view
---> tab2 --> nested view
I couldn't find an easy way to change this behavior. But there's a workaround work for my case. I created a normal ionic view and composed the tab view by myself so no new history stack will be created.
<ion-view title="tabs">
<ion-content padding="false">
<ion-pane>
<ion-nav-view name="tab-content"></ion-nav-view>
</ion-pane>
<div class="tabs tabs-icon-top" style="position: absolute;bottom: 0;">
<a class="tab-item">
<i class="icon ion-home"></i>
Home
</a>
<a class="tab-item">
<i class="icon ion-star"></i>
Favorites
</a>
<a class="tab-item">
<i class="icon ion-gear-a"></i>
Settings
</a>
</div>
</ion-content>
</ion-view>
then you can set up your $stateProvider to load different tab view into tab-content to mimics the ion-tabs behavior. Of course you have to maintain the active states of tabs by yourself.

I am sorry I don't have enough reputation to add a comment.
Ryan's answer worked like a charm for me(not the modify ionic source part), I just want to add a point that if one uses
ng-click="$ionicGoBack()"
instead of
ng-click="goBack()"
the Javascript can be omitted.

Related

Ionic forward view cached when side menu present

I am building a demo application on ionic framework. My demo ionic application has three states :
$stateProvider.state("app", {
abstract : true,
url : "/app",
templateUrl : "app/templates/theme.html"
});
$stateProvider.state("app.dashboard", {
url : "/dashboard",
views : {
"content" : {
templateUrl : "app/modules/dashboard/dashboard.html",
controller : "dashboardController"
},
"settings" : {
templateUrl : "app/templates/settings.html"
},
"menu": {
templateUrl: "app/templates/menu.html"
}
}
});
$stateProvider.state("app.demo", {
url : "/demo",
views : {
"content" : {
templateUrl : "app/modules/demo/demo.html",
controller : "demoController"
}
}
});
And theme.html looks like this :
<ion-side-menus enable-menu-with-back-views="false">
<ion-side-menu-content drag-content="true">
<ion-nav-bar class="bar-stable nav-title-slide-ios7 two-side" align-title="center">
<ion-nav-back-button class="button-clear inverse">
<i class="icon ion-ios7-arrow-back">
</i>< Back
</ion-nav-back-button>
<ion-nav-buttons side="left">
<button menu-toggle="left" id="menuBtn" class="button button-icon icon ion-navicon inverse"></button>
</ion-nav-buttons>
<ion-nav-buttons side="right">
<button menu-toggle="right" id="settingsBtn" class="button button-icon icon ion-gear-b inverse"></button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-nav-view name="content">
</ion-nav-view>
</ion-side-menu-content>
<ion-side-menu side="left">
<ion-nav-view name="menu" animation="slide-left-right"></ion-nav-view>
</ion-side-menu>
<ion-side-menu side="right">
<ion-nav-view name="settings" animation="slide-left-right"></ion-nav-view>
</ion-side-menu>
</ion-side-menus>
Issue is when I am going from app.dashboard to app.demo first time,
demoController is called. Then I go back to app.dashboard. And when
again going to app.demo state any number of times, demoController is
never called. app.demo view is cached. I don't know why.
In addition, I don't want to put cache-view=false or cache false in routing config because that disables the caching of that page totally(Forward & Backward). I want to reload page when I go in forward direction like app.dashboard to app.demo but not to reload page when I go in backward direction like app.demochild(For example) -> app.demo.
If I delete both ion-side-menu tag from my theme.html, the issue gets resolved, demoController is called every time when going in forward direction, But I want both ion-side-menu to be present in my theme.html
I have even disabled the forward caching.
$ionicConfigProvider.views.forwardCache(false);
Any help would be highly appreciated.
Ionic broadcast multiple things while changing a route, like'$ionicView.beforeEnter', '$ionicView.enter' etc.
write condition to check whether its in forward direction / backward direction and call $state.reload() accordingly in your broadcast handler
$scope.$on("$ionicView.beforeEnter", function(event, data){
if()//check for the direction backward / forward
{
$state.reload();
}
});

<ion-side-menus> not working inside <ion-view> on iPhone

I have an application that at the root does not require any ion-side-menus. However, there is one view that does require an ion-side-menu.
For instance, take a restaurant. You may list a bunch of options on the home view (menu, contact, map), but when you click menu you move to a view that list options for breakfast, lunch and dinner. Instead of taking the user to a new view, you'd like to slide out a menu when the user clicks breakfast with all your options.
I was able to implement this quite well, using Android as my development target. However when switching to iPhone, the view completely stops rendering at all!
Below is the ion-view I'm using:
<ion-view view-title="Menu">
<ion-content>
<ion-side-menus enable-menu-with-back-views="false">
<ion-side-menu-content>
<ion-list>
<ion-item ng-repeat="meal in vm.meals" ng-click="vm.onMealClick(meal.name)">
{{meal.name}}
</ion-item>
</ion-list>
</ion-side-menu-content>
<ion-side-menu side="right">
<div class="item item-button-left">
{{vm.selectedMeal}}
<button class="button button-clear button-small" menu-close>
<i class="icon ion-close"></i>
</button>
</div>
<ion-list>
<ion-item>Eggs</ion-item>
<ion-item>Cereal</ion-item>
</ion-list>
</ion-side-menu>
</ion-side-menus>
</ion-content>
And this is the menu toggle binding:
var vm = this;
vm.onMealClick = onMealClick;
function onMealClick(meal) {
vm.selectedMeal = meal;
$ionicSideMenuDelegate.toggleRight();
};
Does anyone know of issues using ion-side-menus inside of an ion-view? In my real application, this provides an extremely organized user-experience, so it's something I'd like to keep pursuing and not change the layout to accommodate.
Thanks for any and all help.

Ionic side menu items back navigation

I am trying to accomplish both tabs and sliding side menu, but can't get back button appear after entering side menu item. I am new to Ionic/Angular Routing,but I am supposing that to make it work I need to manipulate with app.js and states.
<ion-side-menus>
<ion-side-menu-content>
<ion-nav-bar class="bar-stable bar-positive">
<ion-nav-back-button></ion-nav-back-button>
<ion-nav-buttons side="left">
<button menu-toggle="left" class="button button-icon icon ion-navicon" ng-click="toggleRight()"></button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-nav-view></ion-nav-view>
</ion-side-menu-content>
<ion-side-menu side="left">
<header class="bar bar-header bar-balanced">
<h1 class="title">MyApp</h1>
</header>
<ion-content class="has-header">
<ion-list>
<ion-item menu-close ui-sref="about">
About
</ion-item>
</ion-list>
</ion-content>
</ion-side-menu>
</ion-side-menus>
And my apps.js looks like this:
.state('tab', {
url: '/tab',
abstract: true,
templateUrl: 'templates/tabs.html'
})
(...tab states...)
.state('about', {
url: '/about',
templateUrl: 'templates/side/about.html',
controller: 'AboutController',
})
What should I do make back nav-button(or at least make some custom button on navigation bar to redirect home) appear when I am entering one of the side menu items and then template?
have you tried this?
$ionicNavBarDelegate.showBackButton(true);
$ionicNavBarDelegate api guide
You can include below code to enable back button.
< ion-side-menus enable-menu-with-back-views="true">
....
< /ion-side-menus>
http://ionicframework.com/docs/api/directive/ionSideMenus/

ionic link to a view, get the link title to view-title

Here is codepen example. When I click on Scientific Facts button, it is directed to the facts page.
In facts page, I have to manually type view-title="facts", so the header can show title "facts".
Is it possible to get the button text(Scientific Facts) automatically to be the view-title?
http://codepen.io/ionic/pen/odqCz
<html ng-app="ionicApp">
<title>Tabs Example</title>
<link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet">
<script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
<ion-nav-bar class="bar-positive">
<ion-nav-back-button>
</ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view></ion-nav-view>
<script id="templates/tabs.html" type="text/ng-template">
<ion-tabs class="tabs-icon-top tabs-positive">
<ion-tab title="Home" icon="ion-home" href="#/tab/home">
<ion-nav-view name="home-tab"></ion-nav-view>
</ion-tab>
<ion-tab title="About" icon="ion-ios-information" href="#/tab/about">
<ion-nav-view name="about-tab"></ion-nav-view>
</ion-tab>
<ion-tab title="Contact" icon="ion-ios-world" ui-sref="tabs.contact">
<ion-nav-view name="contact-tab"></ion-nav-view>
</ion-tab>
</ion-tabs>
</script>
<script id="templates/home.html" type="text/ng-template">
<ion-view view-title="Home">
<ion-content class="padding">
<p>
<a class="button icon icon-right ion-chevron-right" href="#/tab/facts">Scientific Facts</a>
</p>
</ion-content>
</ion-view>
</script>
<script id="templates/facts.html" type="text/ng-template">
<ion-view view-title="Facts">
<ion-content class="padding">
<p>Banging your head against a wall uses 150 calories an hour.</p>
<p>Dogs have four toes on their hind feet, and five on their front feet.</p>
<p>The ant can lift 50 times its own weight, can pull 30 times its own weight and always falls over on its right side when intoxicated.</p>
<p>A cockroach will live nine days without it's head, before it starves to death.</p>
<p>Polar bears are left handed.</p>
<p>
<a class="button icon ion-home" href="#/tab/home"> Home</a>
<a class="button icon icon-right ion-chevron-right" href="#/tab/facts2">More Facts</a>
</p>
</ion-content>
</ion-view>
</script>
<script id="templates/facts2.html" type="text/ng-template">
<ion-view view-title="Also Factual">
<ion-content class="padding">
<p>111,111,111 x 111,111,111 = 12,345,678,987,654,321</p>
<p>1 in every 4 Americans has appeared on T.V.</p>
<p>11% of the world is left-handed.</p>
<p>1 in 8 Americans has worked at a McDonalds restaurant.</p>
<p>$283,200 is the absolute highest amount of money you can win on Jeopardy.</p>
<p>101 Dalmatians, Peter Pan, Lady and the Tramp, and Mulan are the only Disney cartoons where both parents are present and don't die throughout the movie.</p>
<p>
<a class="button icon ion-home" href="#/tab/home"> Home</a>
<a class="button icon ion-chevron-left" href="#/tab/facts"> Scientific Facts</a>
</p>
</ion-content>
</ion-view>
</script>
<script id="templates/about.html" type="text/ng-template">
<ion-view view-title="About">
<ion-content class="padding">
<h3>Create hybrid mobile apps with the web technologies you love.</h3>
<p>Free and open source, Ionic offers a library of mobile-optimized HTML, CSS and JS components for building highly interactive apps.</p>
<p>Built with Sass and optimized for AngularJS.</p>
<p>
<a class="button icon icon-right ion-chevron-right" href="#/tab/navstack">Tabs Nav Stack</a>
</p>
</ion-content>
</ion-view>
</script>
<script id="templates/nav-stack.html" type="text/ng-template">
<ion-view view-title="Tab Nav Stack">
<ion-content class="padding">
<p><img src="http://ionicframework.com/img/diagrams/tabs-nav-stack.png" style="width:100%"></p>
</ion-content>
</ion-view>
</script>
<script id="templates/contact.html" type="text/ng-template">
<ion-view title="Contact">
<ion-content>
<div class="list">
<div class="item">
#IonicFramework
</div>
<div class="item">
#DriftyTeam
</div>
</div>
</ion-content>
</ion-view>
</script>
I'm not quite sure the motivation behind this request, but one possible way to solve it would be to add the desired title into the URL of the anchor that redirects to your "facts" page, i.e.:
<a class="button icon icon-right ion-chevron-right" href="#/tab/facts?title=Scientific%20Facts">Scientific Facts</a>
If you alter your route to the page to be aware of that query param, you could use the $stateParams service within that page's controller to retrieve that value, i.e.:
.state('tabs.facts', {
url: "/facts?:title",
views: {
'home-tab': {
templateUrl: "templates/facts.html"
}
}
Notice the url "/facts?:title" - the ":title" now becomes a parameter that will be picked up by the $stateParam service. Now within your controller you could just do this:
.controller('FactController', function ($scope, $stateParams) {
$scope.title = $stateParams.title;
});
Now you can reference that title right from your Facts view via {{title}}.
Here is an updated pen that shows this working.
http://codepen.io/anon/pen/OVMbVX
Seems like a lot of effort though, just to pass around the title ;-)
A better approach could be to create a "page names" service, which has all your page names in one place, and then grab that services from both controllers; on the home controller you could use the page name to setup the anchor text, and on the other page use it to setup the page title. Lots of ways to skin this cat.
There are two ways to achieve this:
1) The most obvious one is done with prototypal controller inheritance in angular. You need to declare a controller for the tabs state.
Within the $scope in this controller you can define the title for the button and the header as scope variable, e.x:
$scope.testTitle = 'Scientific Facts';
Now since every other controller inherits from the tabs controller, the testTitle property is also in the inherited scope and can be used to render the title.
Updated codepen: http://codepen.io/anon/pen/mJVOJJ
I would not recommend to do this this way since is hard to know which properties are defined in which controller and this will get very messy with the time.
2) You can declare a service and define the title property there. Than you can inject the service into controller to get the title property.
In this way you keep the $scope clean:
.factory('TitleService', function() {
var titles = {
t1:'foobar',
t3:'baz',
t4:'bar'
};
return titles;
});
Codepen: http://codepen.io/anon/pen/xGZRZM

Angularjs + Ionic Framework: How to create a new route that shows the ion-tabs navigation but without defining a tab for itself?

Long title but here is a better explanation.
I have a template html file called "Login". I define a route in app.js like so
.state('login', {
url: '/login',
templateUrl: 'templates/login.html',
controller: 'createAccountCtrl'
})
By using ui-sref="login" I can link to this template from anywhere which is perfect for my needs.
However the main app uses an abstract route "tab" to load the tabs template which contains the main navigation.
.state('tab.about', {
url: '/about',
views: {
'about-tab': {
templateUrl: 'templates/about.html',
controller: 'aboutCtrl'
}
}
})
<ion-tabs tabs-style="tabs-icon-top" tabs-type="tabs-default">
<!-- Home Tab -->
<ion-tab title="Home" icon="icon ion-home" href="#/tab/home">
<ion-nav-view name="home-tab"></ion-nav-view>
</ion-tab>
<!-- Products Tab -->
<ion-tab title="Earn Points" icon="icon ion-ios7-plus-outline" href="#/tab/retail-store">
<ion-nav-view name="retail-store-tab"></ion-nav-view>
</ion-tab>
</ion-tabs>
My problem is this. I want the Login page to have the main app's navigation like every other page has. That way a user who makes it to the login page, if they don't to login can still navigate off to the home or about page. But, I do not want a navigation tab/icon of its own to show.
Is is possible to just add the tabs html directly to the login.html template file or possibly hide the login icon/tab. I am open to suggestions and help. Thank you!
The tabs are meant to have their own tab icon. So you can't put the login page inside the tabs abstract view without creating a tab icon for it.
Instead of putting the login page under the tab abstract view, you should just put a separate tabbed navigation for the login page.
Load the following view into your index page.
<ion-view title="'Login'">
<ion-content has-header="true" has-footer="true" padding="true">
Login page content goes here
</ion-content>
<div class="tabs tabs-icon-left">
<a class="tab-item" href="#/tab/home">
Home
</a>
<a class="tab-item" href="#/tab/about">
About
</a>
</div>
</ion-view>

Resources