官术网_书友最值得收藏!

Dealing with tabs without Bootstrap UI directives

Bootstrap user interface is very popular and is used by many web developers. The AngularJS community has their own in-built version on top of the Bootstrap JavaScript library, the AngularJS UI directives. However, using it is not always our first option; often, we need a simple solution.

In this recipe, we will see how to build component tabs without Angular UI.

Later in the book, we will see in depth how to use and customize Bootstrap UI directives. Now, we will focus on a simple directive tabs.

In a very basic way, we don't need to use a custom directive to build the tabs. So, let's see two ways to build a simple tab.

Getting ready

For the first example, we need the following code:

<!DOCTYPE html>
<html ng-app="simpleTab">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular.js"></script>
  <title>Simple tab</title>
  <style>
    .tabs-nav {
      padding: 20px 0 0;
      list-style: none;
    }
    .tabs-nav li {
      display: inline;
      margin-right: 20px;
    }
    .tabs-nav a {
      display:inline-block;
      cursor: pointer;
    }
    .tabs-nav .active {
      color: red;
    }
    .tab-content {
      border: 1px solid #ddd;
      padding: 20px;
    }
  </style>
</head>

<div class="tabs-holder" ng-app="simpleTab" ng-init="tab=1">
  <ul class="tabs-nav">
    <li><a ng-click="tab=1" ng-class="{'active' : tab==1}">First tab</a></li>
    <li><a ng-click="tab=2" ng-class="{'active' : tab==2}">Second tab</a></li>
    <li><a ng-click="tab=3" ng-class="{'active' : tab==3}">Third tab</a></li>
  </ul>

  <div class="tabs-container">
    <div class="tab-content" ng-show="tab == 1">
      <h1>First Tab</h1>
      <p>Simple tab 1</p>
    </div>
    <div class="tab-content" ng-show="tab == 2">
      <h1>Second tab</h1>
      <p>Simple tab 2</p>
    </div>

    <div class="tab-content" ng-show="tab == 3">
      <h1>Third Tab</h1>
      <p>Simple tab 3</p>
    </div>
  </div>
</div>
</body>
</html>

For the second example, we need the following code. This time, we're using a controller and an external template. Place the following HTML code in a blank HTML file:

<!DOCTYPE html>
<html ng-app="simpleTabController">
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular.js"></script>
  <title>Simple tab with Controller</title>
  <style>
    .tabs-nav {
      padding: 20px 0 0;
      list-style: none;
    }
    .tabs-nav li {
      display: inline;
      margin-right: 20px;
    }
    .tabs-nav a {
      display:inline-block;
      cursor: pointer;
    }
    .tabs-nav .active {
      color: red;
    }
    .tab-content {
      border: 1px solid #ddd;
      padding: 20px;
    }
  </style>
</head>
<body>
<div class="tabs-holder" ng-app="simpleTabController">
<div id="tabs" ng-controller="TabsCtrl">
  <ul class="tabs-nav">
    <li ng-repeat="tab in tabs"
    ng-class="{active:isActiveTab(tab.url)}"
    ng-click="onClickTab(tab)">{{tab.title}}</li>
  </ul>
  <div id="tab-content">
    <div ng-include="currentTab"></div>
  </div>
  <!--Script templates-->
  <script type="text/ng-template" id="first.html">
    <div class="tab-content" id="1">
      <h1>First Tab</h1>
      <p>Simple tab 1</p>
    </div>
  </script>

  <script type="text/ng-template" id="second.html">
    <div class="tab-content" id="2">
      <h1>Second Tab</h1>
      <p>Simple tab 2</p>
    </div>
  </script>

  <script type="text/ng-template" id="third.html">
    <div class="tab-content" id="3">
      <h1>Third Tab</h1>
      <p>Simple tab 3</p>
    </div>
  </script>
</div>
</div>
</body>
</html>

How to do it…

With the HTML already set up for both examples, let's dive into the controller's code for the second one. Add the following code to a separate file:

angular.module('simpleTabController', [])

.controller('TabsCtrl', ['$scope', function ($scope) {
  $scope.tabs = [{
    title: 'First tab',
    url: 'first.html'
  }, {
    title: 'Second tab',
    url: 'second.html'
  }, {
    title: 'Third tab',
    url: 'third.html'
}];

  $scope.currentTab = 'first.html';

  $scope.onClickTab = function (tab) {
    $scope.currentTab = tab.url;
  }

  $scope.isActiveTab = function(tabUrl) {
    return tabUrl == $scope.currentTab;
  }
}]);

The result of the tabs example is very similar to the following screenshot:

Simple tab layout example

Note that we keep the layout as simple as possible just for the example code.

For the second example, we keep the same stylesheet and layout. In both the examples, we include the CSS inside the head element on the HTML page; you must avoid this on production applications.

How it works…

The first example is pretty intuitive, and we only use the AngularJS built-in directives, such as ng-class and ng-show, to simulate the tab functionality.

<ul class="tabs-nav">
  <li><a ng-click="tab=1" ng-class="{'active' : tab==1}">First tab</a></li>
  <li><a ng-click="tab=2" ng-class="{'active' : tab==2}">Second tab</a></li>
  <li><a ng-click="tab=3" ng-class="{'active' : tab==3}">Third tab</a></li>
</ul>

Internally, the framework recognizes the reverse state of ng-show and hides all the content of tabs 1 and 2. When we click on one of the other tabs, the state changes to show what has been clicked on and hides the others.

This is a simple example, but it is not very flexible.

In the second example, we added a controller to deal with the tabs logic, creating a $scope to hold the tab title and their respective template:

$scope.tabs = [{
  title: 'First tab',
  url: 'first.html'
}, {
  title: 'Second tab',
  url: 'second.html'
}, {
  title: 'Third tab',
  url: 'third.html'
}];

We could easily introduce other elements in this array, such as description, date, and other elements, since we have loaded them from the controller. Although, it is possible to load the tabs content dynamically within this own array. We can also load the templates in external files, as we saw in the beginning of this chapter.

For this, transfer the contents of the script tags (highlighted here) to external files, keeping the names as first.html, second.html, and third.html:

<script type="text/ng-template" id="first.html">
  <div class="tab-content" id="1">
    <h1>First Tab</h1>
    <p>Simple tab 1</p>
  </div>
</script>

Now just remove the script tags from the original HTML file:

<script type="text/ng-template" id="second.html">
  <div class="tab-content" id="2">
    <h1>Second Tab</h1>
    <p>Simple tab 2</p>
  </div>
</script>

<script type="text/ng-template" id="third.html">
  <div class="tab-content" id="3">
    <h1>Third Tab</h1>
    <p>Simple tab 3</p>
  </div>
</script>

Now we can have tabs with external templates.

These were simple examples for creation of tabs without using custom directives, and instead using built-in AngularJS directives. We highlighted the DOM manipulation's simplicity by using controllers rather than customized directives.

There's more…

In addition to the previous examples, we can easily create a directive to use tabs. So, we address all the possibilities in the creation of this interactive component.

Let's see a directive example:

<!DOCTYPE html>
<html >
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.4/angular.js"></script>
  <title>Simple tab with Directive</title>
  <style>
    .tabs-nav {
      padding: 20px 0 0;
      list-style: none;
    }
    .tabs-nav li {
      display: inline;
      margin-right: 20px;
    }
    .tabs-nav a {
      display:inline-block;
      cursor: pointer;
    }
    .tabs-nav .active {
      color: red;
    }
    .tab-content {
      border: 1px solid #ddd;
      padding: 20px;
    }
  </style>
</head>
<body>
  <div ng-app='simpleTabDirective'>
    <ng-tabs>
      <content-tab dat-heading='First tab' dat-tab-active>
        <h1>First Tab</h1>
        <p>Simple tab 1</p>
      </content-tab>
      <content-tab dat-heading='Second tab'>
        <h1>Second Tab</h1>
        <p>Simple tab 2</p>
      </content-tab>
      <content-tab dat-heading='Third tab'>
        <h1>Third Tab</h1>
        <p>Simple tab 3</p>
      </content-tab>
    </ng-tabs>  
  </div>
</body>
</html>

Now, the controller turns into a directive:

var app = angular.module("simpleTabDirective", [])

app.directive('ngTabs', function() {
  return {
    scope: true,
    replace: true,
    restrict: 'E',
    transclude: true,
    template: ' \
<div class="tab-content"> \
  <ul class="tabs-nav"> \
    <li ng-repeat="tab in tabs" \
        ng-class="{ active: currentTab == $index }"> \
      <a ng-click="selectTab($index)"> \
        {{tab}} \
      </a> \
    </li> \
  </ul> \
  <div ng-transclude></div> \
</div>',
    controller: function($scope) {
      $scope.currentTab = 0;
      
      $scope.tabs = [];
      
      $scope.selectTab = function(index) {
        $scope.currentTab = index;
      };
      
      return $scope;
    }
  }
})

app.directive('contentTab', function() {
  return {
    require: '^ngTabs',
    restrict: 'E',
    transclude: true,
    replace: true,
    scope: true,
    template: '<div class="tab-content" ng-show="showTab()" ng-transclude></div>',
    link: function(scope, element, attrs, ngTabs) {
      var tabId = ngTabs.tabs.length;
      
      scope.showTab = function() {
        return tabId == ngTabs.currentTab;
      };
      
      ngTabs.tabs.push(attrs.datHeading);
    }
  }
});

Note that we use the property require to set the dependence of ngTabs. In this way, our tab consists of two directives, one to create the list where we will have the title of the tabs and the second to create the contents of each tab itself. The code is as follows:

<ng-tabs>
  <content-tab dat-heading='First tab'>
  </content-tab>
</ng-tabs>

We can also observe that we have used all the features seen earlier in this chapter, such as ng-click, ng-repeat, and ng-transclude, among others.

See also

  • A great resource that helps us in search of directives, and other related stuff, for the development of applications with AngularJS is the website Angular Modules (http://ngmodules.org/tags/directive)
主站蜘蛛池模板: 夹江县| 北宁市| 遂溪县| 博兴县| 三台县| 保亭| 拜泉县| 广昌县| 上高县| 博爱县| 明光市| 长春市| 库伦旗| 和政县| 嘉峪关市| 施甸县| 布拖县| 宁阳县| 西丰县| 托克逊县| 珠海市| 永丰县| 育儿| 云浮市| 南靖县| 和林格尔县| 漾濞| 沾化县| 潜山县| 曲麻莱县| 虞城县| 张掖市| 资溪县| 墨江| 古蔺县| 烟台市| 施甸县| 连云港市| 杭锦后旗| 习水县| 大同县|