Tab / Tab Bar Navigation is another navigation pattern that found it’s full use on smartphones and tablets. This model is used to divide and store a large amount of different categories of information in a single view. Depending on a screen size or mobile platform application can contain up to 5 tab items, and it can be positioned either at top or bottom of the screen. Some platforms provide horizontal tab bar scrollability if number of tab items surpass 5.
 
Ionic framework tab pattern follow all mentioned rules with few exceptions. Horizontal tab scrollability don’t exist, and you’re not limited to max five tab items. You can use as many tab items as you want.
 
 

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

Example

 
Demo
 
Working embede example
 
Ionic Tab Pattern
 
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 ng-controller="HomeCtrl">

   <ion-nav-bar class="bar-balanced">
      <ion-nav-back-button>
      </ion-nav-back-button>
    </ion-nav-bar>
             
    <ion-nav-view></ion-nav-view>

    <script id="templates/tabs.html" type="text/ng-template">
      <ion-tabs class="tabs-icon-top tabs-balanced">

        <ion-tab title="Search" icon="ion-search" href="#/tab/home">
          <ion-nav-view name="home-tab"></ion-nav-view>
        </ion-tab>

        <ion-tab title="Settings" icon="ion-settings" href="#/tab/about">
          <ion-nav-view name="about-tab"></ion-nav-view>
        </ion-tab>

        <ion-tab title="Sign Out" icon="ion-power" ui-sref="tabs.contact">
          <ion-nav-view name="contact-tab"></ion-nav-view>
        </ion-tab>

      </ion-tabs>
    </script>

    <script id="templates/home.html" type="text/ng-template">
      <ion-view view-title="Search a Movie Database">
        <ion-content>
          <label class="item item-input">
            <i class="icon ion-search placeholder-icon"></i>
            <input type="search" placeholder="Search" ng-model="selected.movieName" ng-change="searchMovieDB()">
          </label>
          <ion-list>
            <div class="list">
    
              <a ng-repeat="movie in movies  | filter: greaterThan('vote_average') | limitTo:settings.itemsPerPage" href="#/movie/{{movie.id}}" class="item item-thumbnail-left">
                <img ng-src="https://image.tmdb.org/t/p/w92{{movie.poster_path}}" onerror="this.src = 'https://www.ginesisnatural.com/images/no_image.jpg';">
                <h2><strong>{{movie.original_title}}</strong></h2>
                <h4>Release Date: <strong>{{movie.release_date}}</strong></h4>
                <h4>Average score: <strong>{{movie.vote_average}}</strong></h4>
              </a>
    
            </div>
          </ion-list>
        </ion-content>
      </ion-view>
    </script>

    <script id="templates/settings.html" type="text/ng-template">
      <ion-view view-title="Application Settings">
        <ion-content>
          <div class="list">
            <label class="item item-input item-floating-label">
              <span class="input-label"><strong>API Key<strong></span>
              <input type="text" placeholder="API Key" ng-model="settings.apiKey">
            </label>
            <div class="item item-divider">
              Items Per Page : {{settings.itemsPerPage}}
            </div>
            <div class="item range range-positive">
              <i class="icon ion-ios7-sunny-outline">1</i>
              <input type="range" name="volume" min="1" max="10" value="4" ng-model="settings.itemsPerPage">
              <i class="icon ion-ios7-sunny">10</i>
            </div>
            <div class="item item-divider">
              Minimum Average Score : {{settings.minimumScore}}
            </div>            
            <div class="item range range-positive">
              <i class="icon ion-ios7-sunny-outline">1</i>
              <input type="range" name="volume" min="1" max="10" value="4" ng-model="settings.minimumScore">
              <i class="icon ion-ios7-sunny">10</i>
            </div>            
          </div>
        </ion-content>
      </ion-view>
    </script>

    <script id="templates/signout.html" type="text/ng-template">
      <ion-view title="Sign Out">

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

app.config(function($stateProvider, $urlRouterProvider) {

  $stateProvider
    .state('tabs', {
      url: "/tab",
      abstract: true,
      templateUrl: "templates/tabs.html"
    })
    .state('tabs.home', {
      url: "/home",
      views: {
        'home-tab': {
          templateUrl: "templates/home.html"
        }
      }
    })
    .state('tabs.about', {
      url: "/about",
      views: {
        'about-tab': {
          templateUrl: "templates/settings.html"
        }
      }
    })
    .state('tabs.contact', {
      url: "/contact",
      views: {
        'contact-tab': {
          templateUrl: "templates/signout.html"
        }
      }
    });


   $urlRouterProvider.otherwise("/tab/home");

});

app.factory('Movies', function($http) {
  var cachedData;
 
  function getData(moviename, apiKey,callback) {
 
    var url = 'http://api.themoviedb.org/3/',
      mode = 'search/movie?query=',
      name = '&query=' + encodeURI(moviename),
      key = '&api_key=' + apiKey;
 
    $http.get(url + mode + key + name).success(function(data) {
 
      cachedData = data.results;
      callback(data.results);
    });
  }
 
  return {
    list: getData,
    find: function(name, callback) {
      console.log(name);
      var movie = cachedData.filter(function(entry) {
        return entry.id == name;
      })[0];
      callback(movie);
    }
  };
 
});

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

  $scope.selected = {
    movieName : 'Batman'
  }
   
  $scope.settings = {
    apiKey : '470fd2ec8853e25d2f8d86f685d2270e',
    itemsPerPage : 5,
    minimumScore : 5
  }   
  
  $scope.greaterThan = function(fieldName){
      return function(item){
        return item[fieldName] > $scope.settings.minimumScore;
      }
  }    
                    
  $scope.searchMovieDB = function() {
 
    Movies.list($scope.selected.movieName, $scope.settings.apiKey , function(movies) {
      $scope.movies = movies;
    });
     
  };
  
  $scope.searchMovieDB(); 
});
 

Tab pattern overview

 
Tab pattern is formed using the ion-tabs directive.
 
<ion-tabs class="tabs-positive tabs-icon-only">
    <!-- Tabs will go here -->
</ion-tabs>
 
For iOS, tabs will appear at the bottom of the screen. For Android, tabs will be at the top of the screen, below the nav-bar. This follows each OS’s design specification but can be configured with the $ionicConfigProvider or via additional classes:
 
<ion-tabs class="tabs-icon-top tabs-positive tabs-top">
    <!-- Top Tab -->
</ion-tabs>
 
<ion-tabs class="tabs-icon-top tabs-positive tabs-bottom">
    <!-- Bottom Tab -->
</ion-tabs>
 
Directive ion-tabs is not limited with a number of inner tabs though it will not look useful if you use too many of them. Smartphones should no use more than four to five tabs:
 
<ion-tabs class="tabs-positive tabs-icon-only">

  <ion-tab title="Home" icon-on="ion-ios-filing" icon-off="ion-ios-filing-outline">
    <!-- Tab 1 content -->
  </ion-tab>

  <ion-tab title="About" icon-on="ion-ios-clock" icon-off="ion-ios-clock-outline">
    <!-- Tab 2 content -->
  </ion-tab>

  <ion-tab title="Settings" icon-on="ion-ios-gear" icon-off="ion-ios-gear-outline">
    <!-- Tab 3 content -->
  </ion-tab>

</ion-tabs>
 
Each tab works as a separate view so it’s advised to use one controller per tab though you can use one controller to cover them all. Article example will use only one because of simplicity, in one of the following articles I will cover multiple controllers.
 
JavaScript routing with tab views should look like this:
 
app.config(function($stateProvider, $urlRouterProvider) {

  $stateProvider
    .state('tabs', {
      url: "/tab",
      abstract: true,
      templateUrl: "templates/tabs.html"
    })
    .state('tabs.home', {
      url: "/home",
      views: {
        'home-tab': {
          templateUrl: "templates/home.html"
        }
      }
    })
    .state('tabs.about', {
      url: "/about",
      views: {
        'about-tab': {
          templateUrl: "templates/about.html"
        }
      }
    })
    .state('tabs.contact', {
      url: "/contact",
      views: {
        'contact-tab': {
          templateUrl: "templates/contact.html"
        }
      }
    });


   $urlRouterProvider.otherwise("/tab/home");

});
 
Continue Reading

  • nuruddin

    thanks a lot for this article, i have one question
    when i use tabs in page and go from non tabs page to tabs page the back button is not appear
    how i can back to prevues page?

  • Liga Do Desconto

    Hi!

    It’s possible to create dynamic tabs? (each with your title and url, of course)

    I want to read a JSON from a web server then build the tab navigation…

    Can you help me?

    Best Regards
    Guilherme Zima