Tab / Tab Bar navigation is another navigation pattern that found it’s full use on smartphones and tablets. This pattern is used to divide and store large amount of different categories of information in a single view. Depending on a screen size or mobile platform an 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.
 
OnsenUI tab pattern follows all mentioned rules with few exceptions. Horizontal tab scrollability don’t exist, and you are 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

Example

 
Demo
 
Embeded working example:
 
OnsenUI Tab Bar Pattern
 
HTML
 
<!DOCTYPE html>
<html>

<head>
  <script src="https://code.angularjs.org/1.3.0/angular.js"></script>
  <script src="http://onsenui.io/OnsenUI/build/js/onsenui.js"></script>
  <link rel="stylesheet" href="https://cdn.rawgit.com/OnsenUI/OnsenUI/1.2.2/build/css/onsenui.css" />
  <link rel="stylesheet" href="https://cdn.rawgit.com/OnsenUI/OnsenUI/1.2.2/build/css/onsen-css-components.css" />
  <link rel="stylesheet" href="https://cdn.rawgit.com/OnsenUI/OnsenUI/1.2.2/build/css/topcoat-mobile-onsen-ios7.css" />
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body ng-controller="MainCtrl">

  <ons-tabbar>
    <ons-tab page="page1.html" label="Search" icon="ion-search" active="true"></ons-tab>
    <ons-tab page="page2.html" label="Settings" icon="ion-settings"></ons-tab>
    <ons-tab page="page3.html" label="Sign Off" icon="ion-power"></ons-tab>
  </ons-tabbar>

  <ons-template id="page1.html">
    <ons-navigator var="myNav">
      <ons-page>
        <ons-toolbar class="toolbar-black">
          <div class="center">Search the Movie Database</div>
        </ons-toolbar>
        <input type="search" class="search-input search-movies-input" placeholder="Search..." style="width: 100%;height: 45px;" ng-model="selected.movieName" ng-change="searchMovieDB()">
 
        <ons-list>
          <ons-list-item class="list-item-container" ng-repeat="movie in movies  | filter: greaterThan('vote_average') | limitTo:settings.itemsPerPage">
 
            <ons-row>
              <ons-col width="95px">
                <img ng-src="https://image.tmdb.org/t/p/w92{{movie.poster_path}}" onerror="this.src = 'https://www.ginesisnatural.com/images/no_image.jpg';" class="thumbnail">
              </ons-col>
              <ons-col>
                <div class="name"><strong>{{movie.original_title}}</strong></div>
                <div class="desc">Release Date: <strong>{{movie.release_date}}</strong></div>
                <div class="desc">Score: <strong>{{movie.vote_average}}</strong></div>
              </ons-col>
              <ons-col width="40px"></ons-col>
            </ons-row> 
 
          </ons-list-item>
 
        </ons-list> 
      </ons-page>
    </ons-navigator>
  </ons-template>

  <ons-template id="page2.html">
    <ons-toolbar>
      <div class="center">Application Settings</div>
    </ons-toolbar>

    <ul class="list">
      <li class="list__header">API Key</li>
      <li class="list__item">
        <input type="text" class="text-input text-input--underbar" ng-model="settings.apiKey" placeholder="underbar text" value="" style="width: 100%;">
      </li>
      <li class="list__header">Items Per Page {{settings.itemsPerPage}}</li>
      <li class="list__item">
        <ons-row>
          <ons-col width="40px">
            <ons-icon icon="" class="lower">1</ons-icon>
          </ons-col>
          <ons-col class="range-wrapper">
            <input type="range" class="range" name="volume" min="1" max="10" value="4" ng-model="settings.itemsPerPage" style="width: 95%;">
          </ons-col>
          <ons-col width="40px">
            <ons-icon icon="">10</ons-icon>
          </ons-col>
        </ons-row>           
      </li>
      <li class="list__header">Minimum Average Score: {{settings.minimumScore}}</li>
      <li class="list__item">
        <ons-row>
          <ons-col width="40px">
            <ons-icon icon="" class="lower">1</ons-icon>
          </ons-col>
          <ons-col class="range-wrapper">
            <input type="range" class="range" name="volume" min="1" max="10" value="4" ng-model="settings.minimumScore" style="width: 95%;">
          </ons-col>
          <ons-col width="40px">
            <ons-icon icon="">10</ons-icon>
          </ons-col>
        </ons-row>         
      </li>      
    </ul>
  </ons-template>

  <ons-template id="page3.html">
    <ons-toolbar>
      <div class="center">Sign Out</div>
    </ons-toolbar>

    <p style="padding-top: 100px; color: #999; text-align: center">Content goes here</p>
  </ons-template>

</body>

</html>
 
JavaScript
 
var module = ons.bootstrap('my-app', ['onsen']);

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

  $scope.searchMovieDB();
});
 
module.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;
  
    console.log(url + mode + key + name);
     
    $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);
    }
  };
  
});
 
CSS
 
.toolbar-black {
  border-color: #111 !important;
  background-color: #444444 !important;
}
 
.toolbar-black .center {
  color: #fff !important;  
}
   
.search-movies-input {
  border-width: 0px !important;
  background-color: #fff !important;
}
 
.list-item-container {
  line-height: 1;
  padding: 15px 0px 15px 15px !important;
}
 
.thumbnail {
  width: 80px;
  height: 120px;
}
  
.name {
  font-weight: 700;
  line-height: 15px;
  font-size: 15px;
  margin-bottom: 6px;
}
  
.desc {
  line-height: 12px;
  font-size: 12px;
  margin-bottom: 5px;
}

.list__item .range {
  margin-top: 5px !important;
}
 

Tab pattern overview

 
Tab pattern is formed using the ons-tabbar directive.
 
<ons-tabbar>
    <!-- Tabs will go here -->
</ons-tabbar>
 
By default, tab bar will display on the bottom of a page. Tab bar position can change using position attribute:
 
<ons-tabbar position="top">
    <!-- Top Tab -->
</ons-tabbar>
 
<ons-tabbar position="bottom">
    <!-- Bottom Tab -->
</ons-tabbar>
 
Directive ons-tabbar 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:
 
<ons-tabbar>
  <ons-tab page="home.html" active="true">
    <ons-icon icon="ion-home"></ons-icon>
    <span style="font-size: 14px">Home</span>
  </ons-tab>
  <ons-tab page="fav.html" active="true">
    <ons-icon icon="ion-star"></ons-icon>
    <span style="font-size: 14px">Favorites</span>
  </ons-tab>
  <ons-tab page="settings.html" active="true">
    <ons-icon icon="ion-gear-a"></ons-icon>
    <span style="font-size: 14px">Settings</span>
  </ons-tab>
</ons-tabbar>
 
Another great thing about OnsenUI is navigation, our tab bar don’t need to use routing for page navigation, instead we only need to connect tab with its page using page attribute:
 
<ons-tabbar>
    <ons-tab page="page1.html" label="Search" icon="ion-search" active="true"></ons-tab>
    <ons-tab page="page2.html" label="Settings" icon="ion-settings"></ons-tab>
    <ons-tab page="page3.html" label="Sign Off" icon="ion-power"></ons-tab>
</ons-tabbar>
 
Because each tab point to separate page it’s advised to use one controller per tab though you can use only one to cover them all. Article example will use only one because of simplicity, in one of the following articles I will cover multiple controllers.
 
Continue Reading