Ionic - both sidemenu and tabs - javascript

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

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){
...
});

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 Side Menu Issue

I'm having an issue with my homepage and side-menu, whenever I try to enter the home page it bounces back to my "otherwise" view. Whenever I remove the implementation of the menu, in the app.js, my homepage works fine. Instead of using the starter-menu https://github.com/driftyco/ionic-starter-sidemenu, I decided to use a blank version, so that I can learn as much as I need to know about Ionic... The following is my code.
app.js
.config(function($stateProvider, $urlRouterProvider)
{
$stateProvider
.state('intial', {
url: '/',
templateUrl: 'auth/Walkthrough.html',
controller: 'WalkthroughCtrl'
})
.state('login', {
url: '/login',
templateUrl: 'auth/Login.html',
controller: 'LoginCtrl'
})
.state('sign', {
url: '/sign',
templateUrl: 'auth/SignUp.html',
controller: 'SignUpCtrl'
})
.state('app', {
url: '/app',
abstract: false,
templateUrl: 'app/menu.html',
controller: 'AppCtrl'
})
.state('app.home', {
url: '/home',
views: {
'menuContent': {
templateUrl: 'app/Home.html',
controller: 'HomeCtrl'
}
}
})
});
Home.html
<ion-view title="Home">
<ion-pane class="animated fadeIn" style="background-color: #4da6b1">
<ion-nav-bar align-title="center">
<ion-nav-title>
<span style="color: white">Home</span>
</ion-nav-title>
<ion-nav-buttons side="left">
<button menu-toggle="left" class="button button-icon icon ion-navicon-round" style="color: white; background-color:#028090;" ></button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-content class="has-header" style="margin-top: 10px;" data-tap-disabled="true">
<!-- <div class=".col" style=" margin-left: 2px;border: 1px solid white; width: 50%; height: 50%; border-radius: 5px;">
</div> -->
</ion-content>
</ion-pane>
</ion-view>
menu.html
<ion-side-menus enable-menu-with-back-views="false">
<ion-side-menu-content>
<ion-nav-bar class="bar-stable nav-title-slide-ios7">
<ion-nav-back-button class="button-clear"><i class="icon ion-ios7-arrow-back"></i>Back</ion-nav-back-button>
</ion-nav-bar>
<ion-nav-view name="menuContent" animation="slide-left-right"></ion-nav-view>
</ion-side-menu-content>
<ion-side-menu side="left">
<header class="bar bar-header bar-stable">
<h1 class="title">Left</h1>
</header>
<ion-content class="has-header">
<ion-list>
<ion-item menu-close ng-click="login()">
Login
</ion-item>
<ion-item menu-close href="#/app/search">
Search
</ion-item>
<ion-item menu-close href="#/app/browse">
Browse
</ion-item>
<ion-item menu-close href="#/app/playlists">
Playlists
</ion-item>
</ion-list>
</ion-content>
</ion-side-menu>
</ion-side-menus>
Please help.
In html page button you dont have ng-click
This is the format for ionic side menus
<ion-side-menu-content>
<!-- Main content, usually <ion-nav-view> -->
</ion-side-menu-content>
<!-- Right menu -->
<ion-side-menu side="right">
</ion-side-menu>
</ion-side-menus>
This should be inside your controller
function ContentController($scope, $ionicSideMenuDelegate) {
$scope.toggleLeft = function() {
$ionicSideMenuDelegate.toggleLeft();
};
}
For more information about ionic side menu please refer this.
Also in href="#/app/browse",
href="#/app/search",
href="#/app/playlists"
All this page is not defined in your .config so create those pages and add them in your .config and you dont need all the href.
For $state.go('home'); you should inject ui.router in your module and download angular-ui-router.min.js and add it to your project or look this so it will work.

TypeError: Cannot read property 'controller' of undefined

The first time I navigate to a nested route, I get this exception, "TypeError: Cannot read property 'controller' of undefined"
It causes my app to not work correctly. However, if I navigate around it starts working perfectly.
The below image shows the values of the variables and the line of code that throws has an undefined controller that causes the problems. This code is part of the Ionic Framework.
Click image to see full size
This is my only JavaScript file that defines the only module.
angular.module("sa", ["ionic"])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function () {
// hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins.Keyboard) {
window.cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
window.StatusBar.styleDefault();
}
});
})
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state("login", {
url: "/login",
templateUrl: "app/manager/login.html"
})
.state("manager", {
abstract: true,
url: "/manager",
templateUrl: "app/manager/menu.html"
})
.state("manager.jobs", {
url: "/jobs",
views: {
"managerContent": {
templateUrl: "app/manager/requested-jobs.html"
}
}
})
.state("manager.detail", {
url: "/detail",
views: {
"managerContent": {
templateUrl: "app/manager/requested-job-detail.html"
}
}
});
$urlRouterProvider.otherwise("/login");
});
This is the login.html that loads correctly. It also allows the button to be clicked and navigate.
<ion-view view-title="Login" >
<ion-nav-bar class="bar-light"></ion-nav-bar>
<ion-content class="has-header" >
<ion-list>
<ion-item href="#/manager/jobs">
Manager
</ion-item>
</ion-list>
</ion-content>
</ion-view>
This is the side menu file.
<ion-side-menus enable-menu-with-back-views="false">
<ion-side-menu-content>
<ion-nav-bar class="bar-light">
<ion-nav-back-button>
</ion-nav-back-button>
<ion-nav-buttons side="left">
<button menu-toggle="left" class="button button-icon icon ion-navicon"></button>
</ion-nav-buttons>
<ion-nav-view name="managerContent"></ion-nav-view>
</ion-nav-bar>
</ion-side-menu-content>
<ion-side-menu side="left">
<ion-header-bar class="bar-assertive">
<span class="title">Cluber</span>
</ion-header-bar>
<ion-content>
<ion-list>
<ion-item class="item-icon-right" menu-close ui-sref="login">
<i class="icon ion-ios-arrow-right icon-accessory"></i>Logout
</ion-item>
</ion-list>
</ion-content>
</ion-side-menu>
</ion-side-menus>
This is the file that gets loaded into the menu content when naviaged to.
<ion-view view-title="Dashboard">
<ion-content has-bouncing has-header="true">
<ion-list>
<ion-item class="item-border item-icon-right" ui-sref="manager.detail">
Clean Apartment
<i class="icon ion-ios-arrow-right icon-accessory"></i>
</ion-item>
<ion-item class="item-border item-icon-right" ui-sref="manager.detail">
Repair Side Walk
<i class="icon ion-ios-arrow-right icon-accessory"></i>
</ion-item>
</ion-list>
</ion-content>
</ion-view>
This is the simplest example I have that always reproduces the JavaScript exception. Again, this only happens the first time the that "manager.jobs" is navigated to.
The problem is with the below line of HTML in the menu.html file. I had this nested inside the <ion-nav-bar>, instead it is required to be a direct descendent of <ion-side-menu-content>.
<ion-nav-view name="managerContent"></ion-nav-view>
self.isInitialized is actually false, which will set enteringHeaderBar to null (two lines above your highlighted one).
You're setting self.isInitialized to true at the end of the function. That's the reason why it fails the first time, but then works (in the next update it is true and enteringHeaderBar will be set to getOffscreenHeaderBar().

Template does not update when using ui-router and ion-tabs

CODE
http://codepen.io/hawkphil/pen/LEBNVB
I have two pages (link1 and link2) from the side menu. Each page has 2 tabs:
link1: tab 1.1 and tab 1.2
link2: tab 2.1 and tab 2.2
I am using ion-tabs for each page to contain the 2 tabs.
This is a very simple design: I want to click on the link1 or link2 to go to appropriate route. But for some reason, the state has changed correctly (see Console) but the actual html template did not get updated. Can you find out what's wrong and how to fix?
There seems to be some caching problem or something.
HTML
<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-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-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-header-bar class="bar-balanced">
<h1 class="title">Left</h1>
</ion-header-bar>
<ion-content>
<ion-list>
<ion-item nav-clear menu-close ui-sref="link1">
Link 1
</ion-item>
<ion-item nav-clear menu-close ui-sref="link2">
Link 2
</ion-item>
</ion-list>
</ion-content>
</ion-side-menu>
<ion-side-menu side="right">
<ion-header-bar class="bar-calm">
<h1 class="title">Right Menu</h1>
</ion-header-bar>
<ion-content>
<div class="list list-inset">
<label class="item item-input">
<i class="icon ion-search placeholder-icon"></i>
<input type="text" placeholder="Search">
</label>
</div>
<div class="list">
<a class="item item-avatar" href="#">
<img src="img/avatar1.jpg">
<h2>Venkman</h2>
<p>Back off, man. I'm a scientist.</p>
</a>
</div>
</ion-content>
</ion-side-menu>
</ion-side-menus>
</ion-side-menus>
<script id="link1.html" type="text/ng-template">
<ion-tabs class="tabs-icon-top tabs-positive">
<ion-tab title="Home" icon="ion-home">
<ion-view view-title="Home">
<ion-content has-header="true" has-tabs="true" padding="true">
<p>Test</p>
<p>Test Tab 1.1</p>
</ion-content>
</ion-view>
</ion-tab>
<ion-tab title="About" icon="ion-ios-information">
<ion-view view-title="Home">
<ion-content has-header="true" has-tabs="true" padding="true">
<p>Test</p>
<p>Test Tab 1.2</p>
</ion-content>
</ion-view>
</ion-tab>
</ion-tabs>
</script>
<script id="link2.html" type="text/ng-template">
<ion-tabs class="tabs-icon-top tabs-positive">
<ion-tab title="Home" icon="ion-home">
<ion-view view-title="Home">
<ion-content has-header="true" has-tabs="true" padding="true">
<p>Test</p>
<p>Test Tab 2.1</p>
</ion-content>
</ion-view>
</ion-tab>
<ion-tab title="About" icon="ion-ios-information">
<ion-view view-title="Home">
<ion-content has-header="true" has-tabs="true" padding="true">
<p>Test</p>
<p>Test Tab 2.2</p>
</ion-content>
</ion-view>
</ion-tab>
</ion-tabs>
</script>
JS
angular.module('ionicApp', ['ionic'])
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('link1', {
url: "/link1",
views: {
'menuContent': {
templateUrl: "link1.html"
}
}
})
.state('link2', {
url: "/link2",
views: {
'menuContent': {
templateUrl: "link2.html"
}
}
});
$urlRouterProvider.otherwise("/link1");
})
.controller('AppCtrl', ['$scope', '$rootScope', '$state', '$stateParams', function($scope, $rootScope, $state, $stateParams) {
$rootScope.$on('$stateChangeSuccess', function(evt, toState, toParams, fromState, fromParams) {
console.log(toState);
});
}])
You are currently referring to the latest release which is 1.0.0-rc.0 which has bug while transition from one state to another it is not loading the view.
Further research found that, they had 14 beta releases from version 1.0.0-beta.1 to 1.0.0-beta.14 after they are now on version 1.0.0-rc.0 which is release candidate.
nav-view is working perfect till 1.0.0-beta.13 version but it stop working after 1.0.0-beta.14(which is last beta release),
I would suggest you to degrade your version to 1.0.0-beta.13, I know depending on beta version is not good thing but still until ionic release stable version you have to rely on it.
Working Codepen with 1.0.0-beta.13
Update:
Your problem is your view are getting cached because by default caching is enabled inside your ionic app.
Straight from Ionic Doc (Latest Release doc 1.0.0-beta.14)
By default, views are cached to improve performance. When a view is
navigated away from, its element is left in the DOM, and its scope is
disconnected from the $watch cycle. When navigating to a view that is
already cached, its scope is then reconnected, and the existing
element that was left in the DOM becomes the active view. This also
allows for the scroll position of previous views to be maintained.Maximum capacity of caching view is 10.
So by mentioning cache: false on $stateProvider states function or disabling cache of nav-view globally by doing $ionicConfigProvider.views.maxCache(0); inside angular config phase.
So in your case this is what exact problem, your 1st view is getting cache & showing it again & again
There are 3 ways to solve this issue
1. Disable cache globally
Disable all caching by setting it to 0, before using it add $ionicConfigProvider dependency.
$ionicConfigProvider.views.maxCache(0);
Codepen
2. Disable cache within state provider
$stateProvider
.state('link1', {
url: "/link1",
cache: false,
views: {
'menuContent': {
templateUrl: "link1.html"
}
}
})
.state('link2', {
url: "/link2",
cache: false,
views: {
'menuContent': {
templateUrl: "link2.html"
}
}
});
Codepen
3. Disable cache with an attribute
<ion-tab title="Home" icon="ion-home">
<ion-view cache-view="false" view-title="Home">
<!-- Ion content here -->
</ion-view>
</ion-tab>
<ion-tab title="About" icon="ion-ios-information">
<ion-view cache-view="false" view-title="Home">
<!-- Ion content here -->
</ion-view>
</ion-tab>
Codepen
I believe the updated approach would be great to implement. Thanks.
Github issue for the same issue link here

Categories