Arjan Wulder

ArjanWulder

Aug 19 2013

AngularJS Bootstrap tab directive and lazy loading

I was looking for an AngularJS tab directive based on Twitter Bootstrap’s markup and CSS that supports lazy loading. So the data of a tab should only be loaded when the tab is active. There are some frameworks like Angular UI and AngularStrap that do have tab directives but none of them supports lazy loading. That’s why I created a tab directive that supports lazy loading.

Tabset directive

'use strict';

angular.module('bootstrap.tabset', [])
.directive('tabset', function () {
  return {
    restrict: 'E',
    replace: true,
    transclude: true,
    controller: function($scope) {
      $scope.templateUrl = '';
      var tabs = $scope.tabs = [];
      var controller = this;

      this.selectTab = function (tab) {
        angular.forEach(tabs, function (tab) {
          tab.selected = false;
        });
        tab.selected = true;
      };

      this.setTabTemplate = function (templateUrl) {
        $scope.templateUrl = templateUrl;
      }

      this.addTab = function (tab) {
        if (tabs.length == 0) {
          controller.selectTab(tab);
        }
        tabs.push(tab);
      };
    },
    template:
      '<div class="row-fluid">' +
        '<div class="row-fluid">' +
          '<div class="nav nav-tabs" ng-transclude></div>' +
        '</div>' +
        '<div class="row-fluid">' +
          '<ng-include src="templateUrl">' +
        '</ng-include></div>' +
      '</div>'
  };
})
.directive('tab', function () {
  return {
    restrict: 'E',
    replace: true,
    require: '^tabset',
    scope: {
      title: '@',
      templateUrl: '@'
    },
    link: function(scope, element, attrs, tabsetController) {
      tabsetController.addTab(scope);

      scope.select = function () {
        tabsetController.selectTab(scope);
      }

      scope.$watch('selected', function () {
        if (scope.selected) {
          tabsetController.setTabTemplate(scope.templateUrl);
        }
      });
    },
    template:
      '<li ng-class="{active: selected}">' +
        '<a href="" ng-click="select()">{{ title }}</a>' +
      '</li>'
  };
});

How to use it

<script src="scripts/directives/tabset.js"></script>
'use strict'

angular.module('myApp', ['bootstrap.tabset']);
<tabset>
  <tab title="Tab 1" template-url="/views/tab1.html"></tab>
  <tab title="Tab 2" template-url="/views/tab2.html"></tab>
  <tab title="Tab 3" template-url="/views/tab3.html"></tab>
</tabset>

Update

I have added demo code at Github.

comments powered by Disqus