Ionic Side Menu - only on one Page - javascript

I'm currently working on an App with the Ionic Framework and I came across the following problem:
In every page of the App there should be a left side menu available. In only one page ('events') there should be another side menu on the right.
Now everything works fine until I visited the 'events'-page once: From that point on every page reveals an empty right side menu when swiping to the left - which, of course, shouldn't be there.
As I'm not sure if I explained the behaviour well enough I made a quick codepen for you to have a look at the app and my full code.
Thank you!
Here you have the important code fragments:
index.html:
<body ng-controller="MainCtrl" ng-app="ionicApp">
<ion-side-menus>
<!--- NAV-MENU LEFT --->
<ion-side-menu side="left">[...]</ion-side-menu>
<!--- EVENTS-MENU RIGHT --->
<ion-side-menu side="right" ng-if="showRightMenu">[...]</ion-side-menu>
<ion-side-menu-content>
<!--- HEADER --->
<ion-nav-bar class="bar bar-header bar-positive">
<ion-nav-buttons side="left">
<button class="button button-clear icon ion-navicon" menu-toggle="left"></button>
</ion-nav-buttons>
<ion-nav-buttons side="right">
<button class="button button-clear icon ion-gear-a" ng-if="showRightMenu" menu-toggle="right"></button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-nav-view></ion-nav-view>
</ion-side-menu-content>
</ion-side-menus>
<script id="home.html" type="text/ng-template">[...]</script>
<script id="events.html" type="text/ng-template">[...]</script>
</body>
app.js:
var app = angular.module('ionicApp', ['ionic', 'ionicApp.controllers']);
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/',
templateUrl: 'home.html'
})
.state('events', {
url: '/events',
templateUrl: 'events.html'
});
$urlRouterProvider.otherwise('/');
});
[...]
app.controller('MainCtrl', function($scope, $state, $rootScope) {
[...]
//set ng-if-variable for the right side menu
$rootScope.$on('$stateChangeSuccess',
function(event, toState, toParams, fromState, fromParams) {
if (toState.name == 'events') {
$scope.showRightMenu = true;
} else {
$scope.showRightMenu = false;
}
//console.log($scope.showRightMenu);
})
function ContentController($scope, $ionicSideMenuDelegate) {
$scope.toggleLeft = function() {
$ionicSideMenuDelegate.toggleLeft();
};
$scope.toggleRight = function() {
$ionicSideMenuDelegate.toggleLeft();
};
}
});
[...]

I came across the same problem, this is the best way I found to solve it.
Firstly I had two templates for my menu, one standard and one include the right menu.
Standard (left only):
<ion-side-menus enable-menu-with-back-views="false" class="dark">
<ion-side-menu-content>
<ion-nav-bar class="bar-stable">
<ion-nav-back-button>
</ion-nav-back-button>
<ion-nav-buttons side="left">
<button class="button button-icon button-clear ion-navicon" menu-toggle="left">
</button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-nav-view name="menuContent"></ion-nav-view>
</ion-side-menu-content>
<ion-side-menu side="left">
<ion-content>
</ion-content>
</ion-side-menu>
</ion-side-menus>
Right menu:
<ion-side-menus enable-menu-with-back-views="false" class="dark">
<ion-side-menu-content>
<ion-nav-bar class="bar-stable">
<ion-nav-back-button>
</ion-nav-back-button>
<ion-nav-buttons side="left">
<button class="button button-icon button-clear ion-navicon" menu-toggle="left">
</button>
</ion-nav-buttons>
<ion-nav-buttons side="right">
<button class="button button-icon button-clear ion-navicon" menu-toggle="right">
</button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-nav-view name="menuContent"></ion-nav-view>
</ion-side-menu-content>
<ion-side-menu side="left">
</ion-side-menu>
<ion-side-menu side="right">
</ion-side-menu>
</ion-side-menus>
The rest of the magic happens with your routing settings, define an abstract route for each menu, and then apply to your route as desired:
$stateProvider
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'templates/menu.html',
controller: 'AppCtrl',
})
.state('app-right', {
url: '/app',
abstract: true,
templateUrl: 'templates/rightMenu.html',
controller: 'AppCtrl',
})
.state('app-right.settings', {
url: '/settings',
views: {
'menuContent': {
templateUrl: 'templates/settings.html'
}
}
})
.state('app.about', {
url: '/about',
views: {
'menuContent': {
templateUrl: 'templates/about.html'
}
}
})

In mainCtrl you have to put some conditions like where you dont want to display left menu.
In below lines of code give ng-hide="" and make this variable true or false from mainCtrl
<ion-nav-buttons side="left">
<button class="button button-clear icon ion-navicon" menu-toggle="left"></button>
</ion-nav-buttons>

Okay, so after a bit more research I stumbled upon the $ionicSideMenuDelegate which can obviously also modify the settings for only one of the side menus. I wasn't aware of this, and so I wanted to share my solution for everyone else who might come across a similar problem:
$rootScope.$on('$stateChangeSuccess',
function(event, toState, toParams, fromState, fromParams){
if (toState.name == 'events'){
$scope.showRightMenu = true;
$ionicSideMenuDelegate._instances[0].right.isEnabled = true;
}
else {
$scope.showRightMenu = false;
$ionicSideMenuDelegate._instances[0].right.isEnabled = false;
}
})

You should use is-enabled attribute instead of ng-if. This will affect swiping as well.
<ion-side-menu is-enabled="showRightMenu" side="right"></ion-side-menu>
See documentation at http://ionicframework.com/docs/api/directive/ionSideMenu/

Related

add controller to a template menu in ionic1

I have an application made in ionic1 and my application contains a template called menu.html and it contains a<ion-side-menus>which is loaded with my other templates and views. the issue is that I want my variables in the $scope can be seen directly in my template menu.html depending on the driver that is currently loaded.
for example in my controller actual I have:
$scope.title="hello";
in menu.html:
{{title}} (should be display "hello")
but my $scope variables are not shown in menu.html
if I add ng-controller = "myControllerController" it works, but I want to avoid this solution, since the contents of my controller will be loaded twice. and I've done the test putting a console.log ("it loads") and this message appears two times. I need that the $scope of menu to be according to the current controller.
this is my code:
menu.html:
<ion-side-menus enable-menu-with-back-views="false">
<ion-side-menu-content>
<ion-nav-bar class="bar-stable">
<ion-nav-back-button>
</ion-nav-back-button>
<ion-nav-buttons side="left">
<button class="button button-icon button-clear ion-navicon" menu-toggle="left" >
</button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-nav-view name="menuContent"></ion-nav-view>
</ion-side-menu-content>
<ion-side-menu id="sidemenu" side="left" >
<ion-header-bar class="bar-stable">
<h1 class="title">{{title}}</h1> <!-- title -->
</ion-header-bar>
<ion-content>
<ion-list>
<ion-item menu-close href="#/app/productos">
Registro
</ion-item>
<ion-item menu-close href="#/app/buscar">
Buscar
</ion-item>
<ion-item menu-close href="#/app/ubicaciones">
UbicaciĆ³n
</ion-item>
</ion-list>
</ion-content>
</ion-side-menu>
</ion-side-menus>
controller actual: myControllerController.js
tinApp.controller('myControllerController', function($scope) {
$scope.title="hello";
});
App.js:
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'templates/menu.html'
})
.state('app.view1', {
url: '/view1',
views: {
'menuContent': {
templateUrl: 'templates/view1.html',
controller: 'myControllerController'
}
}
})
Why not add an event listener to your menu controller that will fire every time a page changes. You can then get the page name every time and use that to set the title. And if its a custom name just add it as one of the pages custom parameters in the route.
$rootScope.$on('$stateChangeStart',function(event, toState, toParams, fromState, fromParams){
...
});

Ionic - both sidemenu and tabs

I need to implement both a sidemenu and tabs on the same screen in my Ionic app project.
It is working (almost). I want my bottom tabs to be visible always, but I also want to be able to navigate to other (then tab) view from the sidemenu.
It should keep all tabs menu visible but with all items inactive.
My states definition:
.config(function($stateProvider, $urlRouterProvider, $ionicConfigProvider) {
$stateProvider
.state('app', {
url: '/app',
abstract: true,
templateUrl: 'templates/base.html'
})
.state('app.locations', { // this view doesn't work, when I navigate to it, it changes view title only.
url: '/locations',
views: {
'menuContent': {
templateUrl: 'templates/views/locations.html',
controller: 'LocationsCtrl'
}
}
})
.state('app.home', {
url: '/home',
views: {
'tab-home': {
templateUrl: 'templates/tabs/home.html',
controller: 'HomeCtrl'
}
}
})
.state('app.history', {
url: '/history',
views: {
'tab-history': {
templateUrl: 'templates/tabs/history.html',
controller: 'HistoryCtrl'
}
}
})
.state('app.messages', {
url: '/messages',
views: {
'tab-messages': {
templateUrl: 'templates/tabs/messages.html',
controller: 'MessagesCtrl'
}
}
});
$urlRouterProvider.otherwise('/app/home');
});
My base.html template:
<ion-side-menus enable-menu-with-back-views="false">
<ion-side-menu-content>
<ion-nav-bar class="bar-stable">
<ion-nav-back-button>
</ion-nav-back-button>
<ion-nav-buttons side="left">
<button class="button button-icon button-clear ion-navicon" menu-toggle="left">
</button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-nav-view name="menuContent"></ion-nav-view> <!-- IS IT OK?? -->
<ion-tabs class="tabs-icon-top tabs-color-active-positive">
<ion-tab title="Home" icon-off="ion-ios-home" icon-on="ion-ios-home" ui-sref="app.home">
<ion-nav-view name="tab-home"></ion-nav-view>
</ion-tab>
<ion-tab title="History" icon-off="ion-ios-clock-outline" icon-on="ion-ios-clock-outline" ui-sref="app.history">
<ion-nav-view name="tab-history"></ion-nav-view>
</ion-tab>
<ion-tab title="Messages" icon-off="ion-ios-email-outline" icon-on="ion-ios-email-outline" ui-sref="app.messages" badge="2" badge-style="badge-assertive">
<ion-nav-view name="tab-messages"></ion-nav-view>
</ion-tab>
</ion-tabs>
</ion-side-menu-content>
<ion-side-menu side="left">
<ion-header-bar class="bar-stable">
<h1 class="title">Left</h1>
</ion-header-bar>
<ion-content>
<ion-list>
<ion-item class="item item-divider">Location: B17726</ion-item>
<ion-item menu-close href="#/app/locations">
Login
</ion-item>
<ion-item menu-close>
Search
</ion-item>
<ion-item menu-close>
Browse
</ion-item>
<ion-item menu-close>
Playlists
</ion-item>
<ion-item class="item item-divider">
General
</ion-item>
</ion-list>
</ion-content>
</ion-side-menu>
</ion-side-menus>
Basically, I want to have bottom tabs always visible, event no of its items is active. When one of tabs is clicked, I want to show it as normal.
Would comment if I could (no rep woes) but here's the track I'm currently looking down if this helps you at all or gives you a flash of inspiration. I'm trying to figure this out as well.
Here's a similar question on the Ionic Forums: http://forum.ionicframework.com/t/show-tab-bar-on-pages-not-children-of-the-tab-bar/726
The last comment mentions an Angular method called $ionicTabsDelegate with a method called showBar(show) which takes a boolean on whether or not to show the tabs bar.
Ref: http://ionicframework.com/docs/api/service/%24ionicTabsDelegate/
Here's the code I've currently produced, though it doesn't seem to work (hopefully it's close)?
index.html
<ion-content class="side-menu-left" ng-controller="AppCtrl">
<ion-list <!--Irrelevant Stuff Here-->>
<ion-item ui-sref="aboutUs" <!--Irrelevant Stuff Here--> ng-click="showTabs()" menu-close>
<i class="icon ion-information-circled"></i>About Us</ion-item>
<!-- More Menu Items Here etc. -->
controllers.js
.controller('AppCtrl', function($scope, $ionicTabsDelegate) {
$scope.showTabs = function() {
$ionicTabsDelegate.showBar(true);
};
});
Edit: Here is another Ionic forum post on this subject along with what seems to be a working Codepen example.
forum.ionicframework.com/t/using-sidemenu-and-tabs-together/2311
codepen.io/gnomeontherun/pen/tbvdH

Nested ion-nav-view implementation

I am trying to learn angular with ionic and trying to understand nested ion-nav-views concept.
Now I have a tabs template code like -
<ion-side-menus enable-menu-with-back-views="false">
<ion-side-menu-content>
<ion-nav-bar class="bar-stable">
<ion-nav-back-button>
</ion-nav-back-button>
<ion-nav-buttons side="left">
<button class="button button-icon button-clear ion-navicon" menu-toggle="left">
</button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-nav-view name="menuContent">
<ion-tabs class="tabs-icon-top tabs-color-active-positive">
<ion-tab title="Show All" icon-off="ion-ios-pulse" icon-on="ion-ios-pulse-strong" href="#/tab/dash">
<ion-nav-view name="tab-dash"></ion-nav-view>
</ion-tab>
<ion-tab title="Collect Stamps" icon-off="ion-ios-chatboxes-outline" icon-on="ion-ios-chatboxes" href="#/tab/chats">
<ion-nav-view name="tab-chats"></ion-nav-view>
</ion-tab>
<ion-tab title="Order Food" icon-off="ion-ios-gear-outline" icon-on="ion-ios-gear" href="#/tab/account">
<ion-nav-view name="tab-account"></ion-nav-view>
</ion-tab>
<ion-tab title="Reserve a table" icon-off="ion-ios-rainy" icon-on="ion-ios-rainy" href="#/tab/account">
<ion-nav-view name="tab-account"></ion-nav-view>
</ion-tab>
</ion-tabs>
</ion-nav-view>
</ion-side-menu-content>
<ion-side-menu side="left">
<ion-header-bar class="bar-stable">
<h1 class="title">Left in Menu</h1>
</ion-header-bar>
<ion-content>
<ion-list>
<ion-item menu-close ng-click="login()">
Login
</ion-item>
<ion-item menu-close href="#/app/search">
Search
</ion-item>
</ion-list>
</ion-content>
</ion-side-menu>
</ion-side-menus>
For app.js code -
$stateProvider
// setup an abstract state for the tabs directive
.state('tab', {
url: '/tab',
abstract: true,
templateUrl: 'templates/tabs.html'
})
// Each tab has its own nav history stack:
.state('tab.dash', {
url: '/dash',
views: {
'tab-dash': {
templateUrl: 'templates/tab-dash.html',
controller: 'DashCtrl'
}
}
})
.state('tab.chats', {
url: '/chats',
views: {
'tab-chats': {
templateUrl: 'templates/tab-chats.html',
controller: 'ChatsCtrl'
}
}
})
.state('tab.chat-detail', {
url: '/chats/:chatId',
views: {
'tab-chats': {
templateUrl: 'templates/chat-detail.html',
controller: 'ChatDetailCtrl'
}
}
})
.state('tab.account', {
url: '/account',
views: {
'tab-account': {
templateUrl: 'templates/tab-account.html',
controller: 'AccountCtrl'
}
}
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/tab/dash');
Now the ion-tabs always load properly but there are never any content for any of the nested nav-views.
So I have the outer nav-view with name as menuContent and inner nav-view with name as "tab-chats" / "tab-dash" etc.
If I remove the outer nav-view then the content gets loaded properly.
I want to understand the reason for same for how I can mention in my app.js state for the nested inner nav-view directly.

ionic routing not working like what I expected

The structure of my app:
The main app.js at root:
angular.module('app', ['ionic',
'app.intro',
'app.main',
'app.services'
])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
......
});
})
.config(function($stateProvider, $urlRouterProvider) {
});
app/intro/intro.js:
angular.module('app.intro',['app.intro.controller'])
.config(function($stateProvider, $urlRouterProvider) {
alert('app.intro');
$stateProvider
.state('intro', {
url: '/',
templateUrl: 'app/intro/index.html',
controller: 'IntroCtrl'
});
$urlRouterProvider.otherwise('/');
});
app/intro/controller.js
angular.module('app.intro.controller',[])
.controller('IntroCtrl',function($scope,$state,$ionicSlideBoxDelegate) {
$scope.startMain = function() {
$state.go('main');
};
});
It works fine. The intro page being shown correctly until I add the main module which is a sidemenu.
app/main/main.js:
angular.module('app.main',['app.main.controller'])
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('main', {
url: '/main',
templateUrl: 'app/main/menu.html',
controller: 'MainCtrl'
})
.state('main.news', {
url: '/news',
views: {
'menuContent': {
templateUrl: 'app/main/news.html'
}
}
})
.state('main.share', {
url: '/share',
views: {
'menuContent': {
templateUrl: 'app/main/share.html'
}
}
});
$urlRouterProvider.otherwise('/main/news');
});
The intro page will not be shown anymore. Instead the news page will always be shown when app starts. I'm very new to ionic so that I'm not very familiar with the url routing. Can anybody tell what I did wrong? Thanks.
Edit:
menu.html:
<ion-side-menus enable-menu-with-back-views="false">
<ion-side-menu-content>
<ion-nav-bar class="bar-positive">
<ion-nav-back-button></ion-nav-back-button>
<ion-nav-buttons side="left">
<button class="button button-icon button-clear ion-navicon" menu-toggle="left"></button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-nav-view name="menuContent"></ion-nav-view>
</ion-side-menu-content>
<ion-side-menu side="left">
<ion-header-bar class="bar-stable">
<h1 class="title">Menu</h1>
</ion-header-bar>
<ion-content>
<ion-list>
<ion-item menu-close href="#/main/news">News</ion-item>
</ion-list>
<ion-list>
<ion-item menu-close ng-click="logout()">Logout</ion-item>
</ion-list>
</ion-content>
</ion-side-menu>
</ion-side-menus>
I believe the issue is the "." in your route names, this bit me too but i believe this refers to a substate and wont do a full route transition. If you remove the dots it should work properly.
Also, $urlRouterProvider.otherwise('/main/news'); will default pages to news

Routing with ionic and angular

I am trying to use Angular, Meteorjs and Ionic Framework. It went easy thanks to urigo:angular and urigo:ionic packages. Unfortunately I cannot figure out how to configure ionic links and angular routing to get it working. I have tried different combination of html5Mode on/off, base href, anchors, etc, nothing works. Every suggestion how to fix it is welcome?
app.js
angular.module('namo', ['angular-meteor', 'ui.router', 'ionic']);
function onReady() {
angular.bootstrap(document, ['namo']);
}
if (Meteor.isCordova) {
angular.element(document).on("deviceready", onReady);
}
else {
angular.element(document).ready(onReady);
}
router
angular.module("namo").config(['$urlRouterProvider', '$stateProvider', '$locationProvider', '$ionicConfigProvider',
function ($urlRouterProvider, $stateProvider, $locationProvider, $ionicConfigProvider) {
$ionicConfigProvider.views.maxCache(0)
$locationProvider.html5Mode(true);
$stateProvider
.state('home', {
url: '/',
views: {
'content' :{
templateUrl: "client/home/views/home.ng.html",
controller: 'HomeCtrl'
}
}
})
.state('user.profile', {
url: '/profile',
views: {
'content' :{
templateUrl: 'client/user/views/profile.ng.html',
controller: 'ProfileCtrl'
}
}
});
$urlRouterProvider.otherwise("/");
}]);
and main layout
<head>
<base href="/">
</head>
<body>
<ion-nav-view></ion-nav-view>
<ion-side-menus enable-menu-with-back-views="false">
<ion-side-menu side="left">
<ion-header-bar class="bar-assertive">
<h1 class="title">Menu</h1>
</ion-header-bar>
<ion-content>
<ul class="list">
<a href="/" class="item" menu-close>Home</a>
<a href="/profile" class="item" menu-close>Profile</a>
</ul>
</ion-content>
</ion-side-menu>
<ion-side-menu-content>
<ion-nav-bar class="bar-positive">
<ion-nav-buttons side="left">
<button class="button button-icon button-clear ion-navicon" menu-toggle="left"></button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-nav-view name="content" animation="slide-left-right"></ion-nav-view>
</ion-side-menu-content>
</ion-side-menus>
</body>
Controllers (home and profile) contains simple "hello home" and "hello profile". Unfortunately only one message is displayed and switching between links does not trigger more messages.
in the router states try to change your views names from content to
home and profile and use the ui-sref instead of href ui-sref="profile"

Categories