<!DOCTYPE html>
<html>

  <head>
    <script data-require="jquery@*" data-semver="2.1.4" src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script data-require="angular.js@1.4.0" data-semver="1.4.0" src="https://code.angularjs.org/1.4.0/angular.js"></script>
    <script data-require="angular-sanitize@*" data-semver="1.4.0" src="https://code.angularjs.org/1.4.0/angular-sanitize.js"></script>
    <link rel="stylesheet" href="style.css" />
  </head>

  <body>
    <div ng-app="MyApp">
      <!-- The tabs custom element is a directive DOM marker for the tabs directive -->
      <tabs id="my-tabs">
        <!--
        
        The tab custom element is a directive DOM market for the tab directive.
        
        The id attribute is the unique identifier for the tab. It is not displayed by the user,
        but is used by the directives to link the tab to the tab content as well as set the active tab.
        
        The caption attribute is the text displayed on the clickable tab caption. This value cannot
        contain HTML.
        
        The content of the tag custom element is the content for the tab. This content can contain
        HTML (its displayed with ng-bind-html using ngSanitize) and is compiled by Angular so it
        can contain directives.
        
        -->
        <tab id="tab1" caption="Tab 1">
          <h2>Tab 1</h2>
          <p>Here is some content...</p>
        </tab>
        <tab id="tab2" caption="Tab 2" active="">
          <h2>Tab 2</h2>
          <p>Here is some content...</p>
        </tab>
        <tab id="tab3" caption="Tab 3">
          <h2>Tab 3</h2>
          <p>Here is some content...</p>
        </tab>
        <tab id="tab4" caption="Tab 4">
          <h2>Tab 4</h2>
          <p>Here is some content...</p>
        </tab>
        <tab id="tab5" caption="Tab 5">
          <h2>Tab 5</h2>
          <p>Here is some content...</p>
        </tab>
      </tabs>
    </div>
    <script src="script.js"></script>
  </body>

</html>
angular.module("MyApp", ["ngSanitize"])
  .directive("tabs", function($compile) {
  
  	return {
  		restrict: "E",
  		controller: function($scope) {
  
  			// registers a tab by adding to the tab array
  			this.registerTab = function(tabId, tabCaption, tabContent, tabActive) {
  
  				$scope.tabs.push({
  					tabId: tabId,
  					tabCaption: tabCaption,
  					tabContent: tabContent
  				});
  				
  				if (tabActive) {
  				  $scope.activeTab = tabId;
  				}
  
  			};
  			

  		},
  		compile: function(tElement, tAttrs) {

  		  return {
  	      // a pre-link function is being using primarily to initialize the tabs array
  	      // so the post-link functions of the child directives can add tabs
  	      // this code could be run from the controller, but is listed here to demonstrate
  	      // the primary use of the pre-link function which is to initialize the scope
  	      // of a parent directive before the post-link functions of child directives execute
  		    pre: function(scope) {
  
  		      // before tabs can be added by the post link functions
  		      // of the child directives, the array must be initialized
  		      scope.tabs = [];
  		      
      			// used to set the active tab when the tab caption is clicked
      			scope.activateTab = function(tabId) {
      				scope.activeTab = tabId;
      			};
  
  		    },
  		    post: function(scope, element, attrs) {
  
            // this should be loaded into the template cache on application load
            // its listed here to simply the code demo
            var tpl =
              "<ul class='tabs'>" + 
      			  "<li ng-repeat='tab in tabs' ng-click='activateTab(tab.tabId)' ng-class=\"{'active':activeTab === tab.tabId}\">" + 
      			  "{{tab.tabCaption}}" +
      			  "</li></ul>" +
      			  "<div class='tab-content' ng-repeat='tab in tabs' ng-if='activeTab === tab.tabId' ng-bind-html='tab.tabContent'></div>";
      			
      			// standard recipes for compiling and linking templates
      			var linkingFn = $compile(tpl);
      			var domElements = linkingFn(scope);
      			
      			// remove the original custom tabs element, and replace with the new DOM elements
      			element.replaceWith(domElements);
      			
      			// this could be simplified to
      			//element.replaceWith($compile(tpl)(scope));
  
    		  }
  	    };
  		    
  	  }
  
  	}
  
  })
  .directive("tab", function() {
  
  	return {
  		restrict: "E",
  		require: "^tabs",
  		link: function(scope, element, attrs, ctrl) {
  			// this will register the tab with the parent directive, the purpose of the custom element is purely
  			// to allow for declarative tabs, the custom tab elements will be removed from the DOM after the
  			// parent directive's post-link function executes
  			ctrl.registerTab(attrs.id, attrs.caption, element.html(), attrs.hasOwnProperty("active"));
  		}
  	};
  
  });
ul.tabs {
    list-style-type: none;
    list-style-position: inside;
    padding: 0px;
    margin: 0px;
}

ul.tabs li {
   display:inline-block;
   border:1px solid black;
   border-top-left-radius:5px;
   border-top-right-radius:5px;
   border-bottom:0px;
   padding:5px;
   font-size:12px;
   font-family: arial;
}

ul.tabs li.active {
  background:navy;
  color:white;
}

div.tab-content {
   border-radius:5px;
   border-top-left-radius:0px;
   border:1px solid black;
   padding:5px;
}

h2, p {
  padding:0;
  margin:0;
}
Example Code for the [Blog Post](https://www.accelebrate.com/blog/transclusion-angularjs-part-2-2/)