Note that this directive comprises two parts: the first simulates the links behavior as tabs, and the second activates the selected panel:

.directive('pane', function() {
  return {
    require: '^customTabs',
    restrict: 'E',
    transclude: true,
    scope: { title: '@' },
    link: function(scope, element, attrs, tabsCtrl) {
      tabsCtrl.addPane(scope);
    },
    // Using inline template
    template:
    '<div class="tab-pane" ng-class="{active: selected}" ng-transclude>' +
    '</div>',
    replace: true
  };
})

It is very common for a directive to be composed of one or more parts. A directive, in this case, depends on the operation of the other. They remain connected using the link property:

link: function(scope, element, attrs, tabsCtrl) {
  tabsCtrl.addPane(scope);
},

There’s more…

We can combine both examples to load external content easily using a controller and an external template in the second example, as performed in the previous examples:

.directive('customTabs', function() {
  return {
    restrict: 'E',
    transclude: true,
    // Declaring scope: {} we using the isolate scope and we can use the directive many times in the same page
    scope: {},
    controller: customCtrl.js,
    // Using external template
    template:app/common/tabs-custom-tpl.html,
    replace: true
  };