I need to show and hide back button in different pages/views. I took reference from Justin Noel:
<body ng-app="starter" ng-controller="AppCtrl">
<ion-nav-bar class="bar-stable">
<ion-nav-back-button hide-back-button="{{hideBackButton}}">
</ion-nav-back-button>
</ion-nav-bar>
</body>
App controller to toggle button display:
.controller('AppCtrl', function($scope, $location) {
var path = $location.path();
if (path.indexOf('submit') != -1)
$scope.hideBackButton = true;
else
$scope.hideBackButton = false;
})
But this doesnt work as controller is called only once but not at the change of view in different states. Also changing the value of $scope.hideBackButton from other controllers(linked to different states) does not have any effect on the button display.
Can anyone tell me how to toggle back-button display on each navigation. What am I missing here?
I had exactly same problem today.
Simplest solution is to use $ionicNavBarDelegate:
.controller('AppCtrl', function($scope, $location, $ionicNavBarDelegate) {
var path = $location.path();
if (path.indexOf('submit') != -1)
$ionicNavBarDelegate.showBackButton(false);
else
$ionicNavBarDelegate.showBackButton(true);
})
You can also wrap hideBackButton value in object and your code will work:
.controller('AppCtrl', function($scope, $location) {
var path = $location.path();
$scope.options = $scope.options || {};
if (path.indexOf('submit') != -1)
$scope.options.hideBackButton = true;
else
$scope.options.hideBackButton = false;
})
It works because in JS (as in many other languages) booleans are passed by value and object are passed by the referance and it affects how default Angular watchers are created.
The downside of this method is that hidding of the button is not as smooth as in other ionic solutions.
Just in case, this is how your html should look like:
1st solution:
<body ng-app="starter" ng-controller="AppCtrl">
<ion-nav-bar class="bar-stable">
<ion-nav-back-button>
</ion-nav-back-button>
</ion-nav-bar>
</body>
2nd solution:
<body ng-app="starter" ng-controller="AppCtrl">
<ion-nav-bar class="bar-stable">
<ion-nav-back-button hide-back-button="{{options.hideBackButton}}">
</ion-nav-back-button>
</ion-nav-bar>
</body>
The hide-back-button attribute on <ion-view> did the trick for me: <ion-view hide-back-button="true">
See the official documentation here.
$ionicHistory.nextViewOptions({
disableBack: true
});
$state.go('app.home');
Ionic 2 & 3:
<ion-navbar [hideBackButton]="true">
A very simple way to achieve this is to apply the menu-close directive to your button/anchor. Technically it's meant for closing the menu, but you can use it on any link and it will bypass the slide animation & won't show the back button.
<a menu-close href="#/home">Home</a>
http://ionicframework.com/docs/api/directive/menuClose/
$ionicHistory.nextViewOptions({
disableBack: false,
historyRoot: true
});
That seems a good option to use, works fine for me.
You can change the cache settings so that when the page is reloaded the controller is called again:
http://ionicframework.com/docs/api/directive/ionNavView/
The hide-back-button attribute should be set on ion-view tag.
I had problems with "hide-back-button", since it hides the menu and the back button.
Somehow this.navCtrl.push played with the back button, in case you want the menu to be displayed using this.nav.setRoot(yourPage)
Related
I have a problem with running my controller after declaring it.
This is my current code:
app.js
var myApp = angular.module('starter', ['ionic']);
myApp.controller ("venueCtrl", function() {
this.test = [];
for (var i = 0; i < 100; i++) {
this.test.push(i);
};
console.log("123");
})
index.html
<body ng-app="starter">
<ion-nav-bar class="bar-stable">
<ion-nav-back-button></ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view></ion-nav-view>
</body>
tab-view.html (the template that I am editing)
<ion-view title = "Venue" ng-controller="venueCtrl as main">
<ion-list>
<ion-item collection-repeat="item in main.test">
{{item}}
</ion-item>
</ion-list>
</ion-view>
What I am trying to do is just listing a list of number from 1 to 100 using collection-repeat. I use console.log to show some debug (I am using serve --lab with console option on). However, the console doesn't show anything. I have tested already to see that the console is working (I put console.log outside of the declaration of the controller). So now I am not so sure what's wrong since I have checked some sources and the controller declaring seems correct to me. Any help would be appreciated. Thanks
I have got a main index page, in which i initially hide the footer bar. But i want to display it when some item is clicked in some child view. I can see in the logs the model is getting changed, but its not getting reflected in the view.
index page:
<body ng-app="starter">
<ion-pane ng-controller="AudioCtrl">
<ion-nav-bar class="bar-positive">
<ion-nav-back-button>
</ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view></ion-nav-view>
<ion-content></ion-content>
<ion-footer-bar ng-hide="musicBar.hide">
<div class="audio-block">
.....
</div>
</ion-footer-bar>
</ion-pane>
</body>
The child view page:
<ion-view ng-controller="AudioCtrl as controller" title="{{selectedCategory}}">
<ion-content>
<ion-list>
<ion-item ng-repeat="item in items" ng-click="$parent.songClicked()">{{item.desc}}</ion-item>
</ion-list>
</ion-content>
</ion-view>
The angular code:
app.controller('AudioCtrl', function ($sce, $scope) {
$scope.musicBar= {
hide: true
};
$scope.songClicked = function(){
console.log($scope.musicBar.hide);
$scope.musicBar.hide = false;
console.log($scope.musicBar.hide);
};
}
);
When i click the item i can see musicBar.hide changing from true to false, but its not reflected in the view. I have also check other similar questions but the solution doesn't work. I have tried using $scope.$digest() and $scope.$apply(), but then i get apply already in progress.
The index.html and the cub view are each managed by their own instance of AudioCtrl, each having their own scope.
The header is made visible when the main view scope's musicBar.hide becomes true, but that never happens, because the subview doesn't modify it. It modifies the sub view scope's musicBar.hide variable.
I don't see any reason why a sub view would have the same controller as the main view. It shouldn't.
I am setting the scope with data but all the time getting empty screen.
tried to use some $scope.$apply but it isn't helping.
I can see the scope.items isn't empty...
I can see values only one I click on other tabs.
my code:
.controller('AccountCtrl', function ($scope, $timeout) {
if (localStorage.getItem("itemHistory") !== null) {
$scope.items = localStorage["itemHistory"].split(',');
$scope.$safeApply($scope);
}
});
tab that navigate to template
<!-- Dashboard Tab -->
<ion-tab title="History" icon-off="ion-ios-pulse" icon-on="ion-ios-pulse-strong" href="/tab/account">
<ion-nav-view name="tab-account"></ion-nav-view>
</ion-tab>
my temp:
<ion-nav-bar>
<ion-nav-back-button>
</ion-nav-back-button>
</ion-nav-bar>
<ion-view view-title="Recent Searches">
<ion-content class="padding">
<ul>
<li ng-repeat="item in items">
{{ item }}</li>
</ul>
</ion-content>
</ion-view>
thanks for helping!
I dont see anywhere in your view where the items is being referred. Can you please provide a jsfiddle where I can see the problem? otherwise just looking at this code, I cant make out anything.
And you should not be using explicit apply in this case. apply is a very dangerous call which has to be used with lot of due diligence. It would trigger a digest cycle that trickles up till the rootscope which is what you may NOT want.
I find the issue, it was simple mistake on app.js didnt set the correct view on the app.js
I can't seem to figure out how to get a back button to appear on a view that contains a ion-side-menus directive.
Here's the absolute simplest example I've come up with:
http://codepen.io/jsplaine/pen/YPxvXL?editors=101.
Note that the ion-views in state x.emptyView and state x.emptySideMenu are children of state x's ion-nav-view.
Here's a more in-depth example, where there exists a side-menu that is actually populated:
http://codepen.io/jsplaine/pen/ZYJRYW?editors=101
Here's the basic router, for the first codepen:
angular.module('ionicApp', ['ionic'])
.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('app', {
url: "/",
templateUrl: "templates/home.html",
controller: 'AppCtrl'
})
.state('x', {
url: "/x",
abstract: true,
template: '<ion-nav-view animation="slide-left-right"/>'
})
.state('x.emptyView', {
url: "/empty-view",
templateUrl: "templates/empty_view_only.html"
})
.state('x.emptySideMenu', {
url: "/empty-side-menu",
templateUrl: "templates/empty_side_menu.html"
})
})
There's a second issue with the more in-depth codepen. Depending on which tab you click first, the 2nd or the 3rd, the corresponding template gets cached for future navigation to BOTH the 2nd and 3rd template. Click the 2nd one first, then the 3rd. Then start over and click the 3rd one first then the 2nd. The fact that this is happening makes me thinking that I'm using ui-router wrong somehow.
I also don't understand why I have to define ion-nav-view in both index.html AND in the abstract state ('x') template. Isn't state 'x' a child of index.html (the empty state)?
Can someone figure out how to modify both codepens so that the back button appears on views containing a ion-side-menus directive, and for the 2nd codepen .. the 2nd and 3rd tab caching issue is resolved?
The solution can be seen here:
http://codepen.io/jsplaine/pen/wBqNmw?editors=101
It seems that ion-side-menus' parent ion-view needs a child ion-nav-bar, and enable-menu-with-back-views must be set to true.
<!-- Side Menu Nav and Burger Defined -->
<script id="templates/side_menu_with_nav.html" type="text/ng-template">
<ion-view view-title="Side Menu with Nav and Burger">
<ion-nav-bar></ion-nav-bar> <!-- HERE -->
<ion-side-menus enable-menu-with-back-views="true">
<ion-side-menu-content>
<ion-nav-bar>
<ion-nav-back-button class="button-icon ion-arrow-left-c"></ion-nav-back-button>
<ion-nav-buttons side="right">
<button class="button button-icon button-clear ion-navicon" menu-toggle="right"></button>
</ion-nav-buttons>
</ion-nav-bar>
....
As the ionic directive/menuToggle docs state: https://github.com/driftyco/ionic/blob/master/js/angular/directive/menuToggle.js#L1
### Button Hidden On Child Views
By default, the menu toggle button will only appear on a root
level side-menu page. Navigating in to child views will hide the menu-
toggle button. They can be made visible on child pages by setting the
enable-menu-with-back-views attribute of the {#link >ionic.directive:ionSideMenus}
directive to true.
I wonder if the authors didn't take your case into account. Their model is a slide-in menu that only slides in partially and can be toggled with a menu icon. So you may be a bit off paradigm but this seemed to work for me albeit a bit lame for duplicating the nav-bar code in the template.
<script id="templates/empty_side_menu.html" type="text/ng-template">
<ion-view view-title="Empty side menu">
<ion-nav-bar align-title="center" class="nav-title-slide-ios7 bar-stable">
<ion-nav-back-button class="button-icon ion-arrow-left-c">
</ion-nav-back-button>
</ion-nav-bar>
<ion-side-menus>
</ion-side-menus>
</ion-view>
</script>
In the ionic framework I am trying to hide the menu button conditionally. For other reasons I had to split the menu in its own controller (I don't want to completly re-render the menu and header bar on a refresh), so the header is not in ion-view. I created a watcher on the conditional variable (a stateparam) in the controller of the header. The console log outputs the conditional variable correctly, but the view is not updated (the menu button is always showing).
This is the template:
<ion-side-menus>
<ion-side-menu-content>
<ion-nav-bar class="bar-stable nav-title-slide-ios7">
<ion-nav-back-button ng-if="!isHome" class="button-clear"><i class="icon ion-ios7-arrow-back"></i>Back</ion-nav-back-button>
<button ng-if="isHome" menu-toggle="left" class="button button-icon icon ion-navicon"></button>
<h1 class="title">Title</h1>
</ion-nav-bar>
<ion-nav-view name="menuContent" animation="slide-left-right"></ion-nav-view>
</ion-side-menu-content>
...
</ion-side-menus>
And in the controller:
$scope.$watch(function(){
return $stateParams.contentUrl;
},
function(newVal){
console.log(newVal);
if(!newVal || newVal === 'someParam'){
$timeout(function(){
$scope.$apply(function(){
$scope.isHome = true;
});
console.log("home");
});
} else {
$timeout(function(){
$scope.$apply(function(){
$scope.isHome = false;
});
console.log("not home");
});
}
});
Is there an easier way? Or am I missing something here?
You can use the hide-back-button attribute on the <ion-view> element to declare if that view should hide the back button by default.
http://ionicframework.com/docs/nightly/api/directive/ionView/
<ion-view hide-back-button="true">
<!-- view contents -->
</ion-view>
A kinda dirty workaround would be to give those buttons an id and then use jqlite to hide them like this in the controller:
angular.element(document.querySelector('#back-button')).addClass('hidden');
Setting hide-back-button to false did not work for me. However, in my case the easier solution was to have
<ion-nav-buttons side="left"></ion-nav-buttons>
inside <ion-view>. This is to just include a empty left side nav buttons. This did the trick for me.
It can be done in a easy way:
<ion-side-menus enable-menu-with-back-views = "true">
and on the specific pages where you want to hide the Menu and nav bar, let say your Login Page(inside your login Controller), just type- don't forget to include specified objects inside the controller function.
$scope.$on('$ionicView.beforeEnter', function (event) {
$scope.$root.showMenuIcon = false;
$ionicSideMenuDelegate.canDragContent(false);
});
$scope.$on('$ionicView.beforeLeave', function (event) {
$scope.$root.showMenuIcon = true;
$ionicSideMenuDelegate.canDragContent(true);
});