Ionic Framework | Mixing Different UI patterns

Written by on April 9, 2015

Ionic Framework | Mixing Different UI patterns

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, you need further clarification, something is not working or you have a request for another Ionic post? Furthermore, leave me a comment below if you don't like something about this blog, if something is bugging you, don't like how I'm doing stuff here. Feel free to comment below, subscribe to my blog, mail me to dragan.gaic@gmail.com. Thanks and have a nice day!

Table of Contents

[spoiler title=” Click here if you want to see other tutorials; or articles about Ionic themes, templates, plugins …”]

Tutorials

Other Resources (themes, templates, plugins, Cordova plugins, starter apps)

Cordova Plugin Tutorials


[/spoiler]

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

Categories

40 thoughts on “Ionic Framework | Mixing Different UI patterns”

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

  2. 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.

  3. 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?

  4. 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…

  5. 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.

  6. 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

  7. 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.

    • 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…

  8. 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!

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

  10. 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.

  11. 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.

  12. 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

Leave a Reply