My previous article covered Ionic Framework UI patterns, this one will show you how to mix them properly. We are talking about an important topic here, UI patterns can cover one or more pages, but not all of them have a same priority or can be on a same level. For example, if you want to combine Tab pattern with Side menu pattern, one of them (Tab) can only work as a child of the other one (Side menu).
 
 

Note: If this tutorial was helpful, need further clarification, something is not working or do you have a request for another Ionic post? Furthermore, if you don't like something about this blog, if something is bugging you, don't like how I'm doing stuff here, again leave me a comment below. I'm here to help you, I expect the same from you. Feel free to comment below, subscribe to my blog, mail me to dragan.gaic@gmail.com, or follow and mention me on twitter (@gajotres). Thanks and have a nice day!

PS. If you want my help, if possible (even if it takes you some time to do that), create a working example I can play with. Use Plunker for AngularJS based questions or jsFiddle for jQuery/jQuery Mobile based questions.


 

Table of Contents

Click here if you want to see other tutorials; or articles about Ionic themes, templates, plugins ...

Introduction

 
We will cover four mostly used UI pattern combinations. Leave me a comment below if you want to see some other kind of combination, and I’ll add it to this article.
 
UI pattern combinations:
 
  1. Side menu + Tab combination
  2. Side menu + Master Detail combination
  3. Two Side menus combination
  4. Side menu + Tab bar + Master Detail combination
 

Side menu + Tab combination

 
When working with Ionic Framework UI patterns you must follow certain rules. First one, Sliding menu always has a top ordering priority, you will see it, in this case.
 
If you take a look at provided example (below) you will see that we’re starting with a side menu directive.
 
One part of a directive, namely ion-side-menu-content, points to content section, including automatic back navigation and inner navigation (all thanks to routing set in app.js file). Second directive part, namely ion-side-menu points to left menu content.
 
Content section, in our case contains Tab component, which again thanks to routing points to inner tab pages.
 
Demo
 
Embeded working example:
 
Ionic Side menu + Tab combination
 
HTML
 
<!DOCTYPE html>
<html ng-app="myApp">

	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
		<title>Ionic Framework Example</title>
		<link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet"/>
		<script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
		<script src="app.js"></script>
	</head>

	<body>

    <ion-side-menus>
      
      <ion-pane ion-side-menu-content>
        <ion-nav-bar class="bar-positive nav-title-slide-ios7">
          <ion-nav-back-button class="button-icon"><span class="icon ion-ios7-arrow-left"></span></ion-nav-back-button>
        </ion-nav-bar>
        <ion-nav-view></ion-nav-view>
      </ion-pane>

      <ion-side-menu side="left">
        <ion-header-bar class="bar bar-header bar-dark"></ion-header-bar>
        <ion-content has-header="true">
          <ion-list>
            <ion-item href="#/" menu-close>Home</ion-item>
            <ion-item href="#/about" menu-close>About</ion-item>
          </ion-list>
        </ion-content>
      </ion-side-menu>
      
    </ion-side-menus>
    
    <script id="tabs.html" type="text/ng-template">
      <ion-view title="Home">

        <ion-nav-buttons side="left">
          <button class="button button-icon button-clear ion-navicon" ng-click="openMenu()"></button>
        </ion-nav-buttons> 
        

        <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="Settings" icon="ion-gear-a" href="#/tab/settings" >
            <ion-nav-view name="settings-tab"></ion-nav-view>
          </ion-tab>

          <ion-tab title="Sign-Out" icon="ion-log-out">
          </ion-tab>

        </ion-tabs>
      </ion-view>
    </script>
    
    <script id="home.html" type="text/ng-template">
      <ion-view title="Home">
        <ion-nav-buttons side="left">
          <button class="button button-icon button-clear ion-navicon" ng-click="openMenu()"></button>
        </ion-nav-buttons>        
        <ion-content padding="true">
          <h1 style="text-align: center;">Home Page</h1>
        </ion-content>
      </ion-view>
    </script>    
    
    <script id="settings.html" type="text/ng-template">
      <ion-view title="About">
        <ion-nav-buttons side="left">
          <button class="button button-icon button-clear ion-navicon" ng-click="openMenu()"></button>
        </ion-nav-buttons>         
        <ion-content padding="true">
          <h1 style="text-align: center;">Settings  Page</h1>
        </ion-content>
      </ion-view>
    </script>    
    
    <script id="about.html" type="text/ng-template">
      <ion-view title="About">
        <ion-nav-buttons side="left">
          <button class="button button-icon button-clear ion-navicon" ng-click="openMenu()"></button>
        </ion-nav-buttons>        
        <ion-content padding="true">
          <h1 style="text-align: center;">About Page</h1>
        </ion-content>
      </ion-view>
    </script>        

	</body>
</html>
 
JavaScript
 
var app = angular.module('myApp', ['ionic']);

app.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state('tabs', {
      url: '/tab',
      controller: 'TabsCtrl',
      templateUrl: 'tabs.html'
    })
    .state('tabs.home', {
      url: '/home',
      views: {
        'home-tab': {
          templateUrl: 'home.html',
          controller: 'HomeTabCtrl'
        }
      }
    })  
    .state('tabs.settings', {
      url: '/settings',
      views: {
        'settings-tab': {
          templateUrl: 'settings.html'
        }
      }
    })    
    .state('about', {
      url: '/about',
      controller: 'AboutCtrl',
      templateUrl: 'about.html'
    });

  $urlRouterProvider.otherwise('/tab');
});

app.controller('TabsCtrl', function($scope, $ionicSideMenuDelegate) {
  
  $scope.openMenu = function () {
    $ionicSideMenuDelegate.toggleLeft();
  }
  
});

app.controller('HomeTabCtrl', function($scope, $ionicSideMenuDelegate) {

});

app.controller('AboutCtrl', function($scope, $ionicSideMenuDelegate) {
  $scope.openMenu = function () {
    $ionicSideMenuDelegate.toggleLeft();
  }
});
 

Side menu + Master Detail combination

 
This example, like a previous one, starts with side menu directive.
 
One part of a directive, namely ion-side-menu-content, points to content section, including automatic back navigation and inner navigation (all thanks to routing set in app.js file). Second directive part, namely ion-side-menu points to left menu content.
 
Content section, in our case contains Master Detail component, which again thanks to routing points to inner detail pages.
 
Demo
 
Embeded working example:
 
Ionic Side menu + Master Detail combination
 
HTML
 
<!DOCTYPE html>
<html ng-app="myApp">

	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width" />
		<title>Ionic Framework Example</title>
		<link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet"/>
		<script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
		<script src="app.js"></script>
	</head>

	<body>

    <ion-side-menus>
      
      <ion-pane ion-side-menu-content>
        <ion-nav-bar class="bar-balanced nav-title-slide-ios7">
          <ion-nav-back-button class="button-clear">
            <i class="ion-arrow-left-c"></i> Back
          </ion-nav-back-button>
        </ion-nav-bar>
        <ion-nav-view></ion-nav-view>
      </ion-pane>

      <ion-side-menu side="left">
        <ion-header-bar class="bar bar-header bar-dark"></ion-header-bar>
        <ion-content has-header="true">
          <ion-list>
            <ion-item href="#/" menu-close>Home</ion-item>
            <ion-item href="#/settings" menu-close>Settings</ion-item>
          </ion-list>
        </ion-content>
      </ion-side-menu>
      
    </ion-side-menus>
    
    <script id="home.html" type="text/ng-template">
      <ion-view title="Home">
        <ion-nav-buttons side="left">
          <button class="button button-icon button-clear ion-navicon" ng-click="openMenu()"></button>
        </ion-nav-buttons>          
        <ion-content has-header="true">
            <ion-item href="#/second">Second Page</ion-item>
            <ion-item href="#/third">Third Page</ion-item>
        </ion-content>      
      </ion-view>
    </script>
    
    <script id="second.html" type="text/ng-template">
      <ion-view title="Second Page">
        <ion-content has-header="true" padding="true">
          <a class="button icon-left ion-home" href="#/">Go back!</a>
        </ion-content>
      </ion-view>
    </script>
    
    <script id="third.html" type="text/ng-template">
      <ion-view  title="Third Page">
        <ion-content has-header="true" padding="true">
          <a class="button icon-left ion-home" href="#/">Go back!</a>
        </ion-content>
      </ion-view>
    </script>  
    
    <script id="settings.html" type="text/ng-template">
      <ion-view title="Settings Page">
        <ion-nav-buttons side="left">
          <button class="button button-icon button-clear ion-navicon" ng-click="openMenu()"></button>
        </ion-nav-buttons> 
        
        <ion-content padding="true">
          <h1 style="text-align: center;">Settings</h1>
        </ion-content>
      </ion-view>
    </script>    

	</body>
</html>
 
JavaScript
 
var app = angular.module('myApp', ['ionic']);

app.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state('home', {
      url: '/',
      controller: 'HomeCtrl',
      templateUrl: 'home.html'
    })
    .state('settings', {
      url: '/settings',
      controller: 'SettingsCtrl',      
      templateUrl: 'settings.html'
    })
    .state('second', {
      url: '/second',
      templateUrl: 'second.html'
    })
    .state('third', {
      url: '/third',
      templateUrl: 'third.html'
    });   
  $urlRouterProvider.otherwise('/');
});

app.controller('HomeCtrl', function($scope, $ionicSideMenuDelegate) {
  $scope.openMenu = function () {
    $ionicSideMenuDelegate.toggleLeft();
  };
});

app.controller('SettingsCtrl', function($scope, $ionicHistory, $ionicSideMenuDelegate) {
  $scope.myGoBack = function() {
     $ionicHistory.goBack()
  };
  $scope.openMenu = function () {
    $ionicSideMenuDelegate.toggleLeft();
  };  
});
 
Continue Reading

  • leob

    Great article, this saved me some headaches while trying to figure out how to combine menus with tabs and so on.

  • Arvind Bhardwaj

    Thats awesome. Thanks for your work!

  • Harshdeep Sangwan

    Hi. I actually need help. In the [SIDE MENU + TAB BAR + MASTER DETAIL] if I add more items to the list, it doesn’t scroll. Can you please help me with this as I am working with same mix of ui patterns and I am stuck with this problem.

  • Rubén Valseca

    Thank you so much, helped me a lot! 🙂

    • You’re welcome 🙂 Tell me one thing, was this tutorial informative for you? Would you like me to include something else?

  • adalberto Joco

    Awesome article, you made my day.

    • Thank you for this comment and proactive mail, I wish more people can be like you 🙂

  • Owltastic

    Hi Dragan! I just completed your Side Menu + Master Detail tutorial. I’m now trying to pull data from a Cloudant database into my Ionic app. I want to have a list of species display on the master page (or home.html in your example) – when the user clicks on a species, it will take them to the detail page (second.html in your example). Could you point me to one of your tutorials or another tutorial that could help me understand how to do this?

  • Dmitry Isakov

    Hi guys! I just implemented twosidemenusplustabs pattern but faced very strange issue. When accessing left side menu it opens mixed with the right side. Looks like they are everlapping…

    • Can you create a working example and I’ll check it for you?

  • shoaibbhimani

    Thanks helped me a lot

  • abhimanyu choudhary

    Hi Dragan,

    Great article, helped me with the two side menus. I need to add one notification and cart icon before the right side menu icon. How can I achieve this ?

    • My advice, ask this question at the official Ionic forum. Also don’t forget to provide a working example and specific instructions what you want to achieve. This way someone will certainly create you a working example.

  • Guille Acosta

    Hi There, you made an excellent work. I just tried side menu + tab bar + master detail combination and I’m not being able to scroll my app.
    my home.html looks like:
    <ion-view

    • Dmitry Isakov

      I have the same issue (((

      • Have you tried to use my example or have you modified it with your code?

        • Guille Acosta

          Nope, I didn’t modified anything, just incude some cards divs with ng-repeat. I’ll try to make a little codepen to show yoy.

  • By default, your page will not auto scroll if you add more content than available page height. But you can go around that, just use this method each time you add a new line:

    $ionicScrollDelegate.scrollBottom(false);

    Use true if you want to animate it.

    Here’s a working example: http://plnkr.co/edit/VkkgWSgA7An3r0wpN11b?p=preview

    And let me thank you, you’re actually one of a few people who cared enough to post a working example.

    • Dmitry Isakov

      Thx a lot. Now I know that I have to use $ionicScrollDelegate.scrollBottom(false);

      But the problem is still there (((
      Every time I try to biuld a local test sample or plnkr one it works, but as soon as I return to my app-in-progress it fails to scroll (((
      It can scroll using tap on phone or mouse on laptop but doest scroll when I add new msgs programmatically (((

      Tied of this issue… spent more than a week to resolve it…

      • Are you receiving errors at that point?

        • Dmitry Isakov

          No errors in console. It looks like $ionicScrollDelegate.scrollBottom is working (i have console.log at that point) but the content doesnt move… I think that $ionicScrollDelegate.scrollBottom doesnt understant what to scroll…

          • Let’s do a small test. Each time you add something new output page height to console.log. Previously mentioned function will not work if page height is not changing.

            For example, if newly added content is floating it will not affect page height.

          • Dmitry Isakov

            Great idea. Just a quick qn: how to check height and what particular dom-element to measure according to the header-content (list)-footer structure?

          • Dmitry Isakov

            $window.innerHeight = 667 (for my laptop)
            This is always the same wether there are less or more list items, wether they fit to screen or not.

          • Where are you testing your app? Desktop browser or smartphone?

          • Dmitry Isakov

            Laptop browser (Chrome).

          • I forgot one thing, page height is always the same. You will need to look at ion-content height. Google this topic, you’ll find several solutions.

          • Dmitry Isakov

            Can you give me any other ideas to check? Why is the height always the same?

          • Dmitry Isakov

            All the content is simply

            {{message.username}} : {{message.content}}

  • Thanks for the great Example (Tabs + Sidebar) !

  • mugshepherd

    These are great – thanks so much for taking the time to show how to mix patterns like this. Any chance you could do the same for OnsenUI? Regardless – super helpful, and love all your tutorials. Keep up the good work!

  • adevx5

    Incredible! These work out of the box, with the nightlies. The first sidemenu+tabs that actually works.
    Thank you so much.

  • Warren Jewell

    I have problems with the sidemenu+tabs. Taking exactly what you posted, it works in Plunker, it works in Ripple (from inside Visual Studio), but it doesn’t work on an actual Android device (Nexus 7). All I get on the Nexus is “Home” and “About” written on the top left corner of the screen. Any thoughts? Thanks.

  • Israel Asha

    Great work on the article. i implemented the first (side menu + tab combination) and it worked except for when i click menu items, i don’t get redirected to the page.

  • Israel Asha

    i tried separating the ion-side-menus to a different file so i would just have the ion-nav-view in the index page but my app just shows a white blank page when debugging. how can i achieve that pls