OnsenUI | Working With Sliding Menu Pattern

Written by on April 9, 2015

OnsenUI | Working With Sliding Menu Pattern

Sliding Menu pattern became very popular several years ago on mobile devices and tablets, it’s also known as Navigation Drawer or Side Menu. It works as a single fixed menu (or a set of two fixed menus) that will slide out from any page edge. The menu can also be used in combination with the body moving to the left or right side (body is then “pushed”).

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, this is the 6th tutorial out of 12 total.”]




Embeded working example:
OnsenUI Sliding Menu Pattern

  <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" />
  <script src="script.js"></script>
<body ng-controller="MainController">
  <ons-sliding-menu menu-page="menu.html" main-page="home.html" side="left" var="menu" type="reveal" max-slide-distance="260px" swipable="true">
  <ons-template id="menu.html">
    <ons-page modifier="menu-page">
      <ons-toolbar modifier="transparent" class="toolbar-black">
        <div class="center">Filter Movies</div>
      <ul class="list">
        <li class="list__item list__item--tappable" ng-repeat="sort in sorting">
          <label class="radio-button radio-button--list-item">
            <input type="radio" name="b" ng-model="selected.score" ng-value="{{sort.score}}" checked="checked" ng-change="setSelectedScoreRane()">
            <div class="radio-button__checkmark radio-button--list-item__checkmark"></div>
  <ons-template id="home.html">
    <ons-navigator var="myNav">
        <ons-toolbar class="toolbar-black">
          <div class="left">
            <ons-toolbar-button ng-click="menu.toggle()">
              <ons-icon icon="ion-navicon" size="28px" fixed-width="false"></ons-icon>
          <div class="center">Search the Movie Database</div>
        <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-item class="list-item-container" ng-repeat="movie in movies  | filter: greaterThan('vote_average')">

              <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">
                <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 width="40px"></ons-col>


var module = ons.bootstrap('my-app', ['onsen']);

module.controller('MainController', function($scope, Movies) {

  $scope.sorting = [{score: 9, name : 'Score more then 9'}, 
                    {score: 8, name : 'Score more then 8'}, 
                    {score: 7, name : 'Score more then 7'}, 
                    {score: 6, name : 'Score more then 6'}, 
                    {score: 5, name : 'Score more then 5'}, 
                    {score: 4, name : 'Score more then 4'}, 
                    {score: 3, name : 'Score more then 3'}, 
                    {score: 2, name : 'Score more then 2'}, 
                    {score: 1, name : 'Score more then 1'},                    
                    {score: 0, name : 'Show me every movie'}];    
  $scope.selected = {
    score : 0,
    movieName : 'Batman'
  $scope.searchMovieDB = function() {
    Movies.list($scope.selected.movieName, function(movies) {
      $scope.movies = movies;
  $scope.greaterThan = function(fieldName){
      return function(item){
        return item[fieldName] > $scope.selected.score;
  $scope.setSelectedScoreRane = function(score){


module.factory('Movies', function($http) {
  var cachedData;
  function getData(moviename, callback) {
    var url = 'http://api.themoviedb.org/3/',
      mode = 'search/movie?query=',
      name = '&query=' + encodeURI(moviename),
      key = '&api_key=470fd2ec8853e25d2f8d86f685d2270e';
    console.log(url + mode + key + name);
    $http.get(url + mode + key + name).success(function(data) {
      cachedData = data.results;
  return {
    list: getData,
    find: function(name, callback) {
      var movie = cachedData.filter(function(entry) {
        return entry.id == name;
.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 0 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;

Sliding menu overview

Sliding menu pattern directive is formed from just one element:



Everything else is configurable through various attributes:

<ons-sliding-menu menu-page="menu.html" main-page="home.html" side="left" var="menu" type="reveal" max-slide-distance="260px" swipable="true"></ons-sliding-menu>

Attribute main-page points to main application page (home.html) while attribute menu-page points to the menu holding page (menu.html). This is almost everything you need to know about Sliding menu, at least from the perspective of this article.

Continue Reading


Leave a Reply