I can not solve this problem.

It is necessary to create tabs with distributed logic for navigation and content (different directives), they communicate with each other using events.

There are no problems with the navigation directive.

All questions about the directive with the display of content. There is a <tabs> directive and there are many <tab> directives within it with a unique attribute key. Each <tab> may contain a different directive / expression / just html. <tab> shown only when the key in its attribute is equal to the variable at the parent <tabs> . It is impossible to implement such a structure.

  • How do I pass the value of the variable item.key to an attribute directive with ng-repeat and ng-transclude ? (example <tab key="{{item.key}}" repeat="item in items"> )
  • How do I access the <tab> directive to the selectedTabKey variable of the parent <tabs> ?

 var app = angular.module("app", []); var $ = angular.element; app.run(function($templateCache, $rootScope) { $rootScope.items = [ {key:1,value:'a'}, {key:2,value:'b'}, {key:3,value:'c'} ]; }); app.directive( "tabs", function() { return { restrict: "AE", scope: true, transclude: true, replace: true, template: "<div ng-transclude></div>", link: function(scope, elem, attr, ctrl) { scope.selectedTabKey = 2; // TODO: changing the selectedTabKey value // want to show/hide the related tab } }; }); app.directive( "tab", function($compile) { return { restrict: "AE", transclude: true, replace: true, template: "<div><span transclude></span></div>", link: function( scope, elem, attr, ctrl, transclude ) { var transc = $(elem[0].querySelector( "[transclude]" )); transclude( scope, function( childs ) { transc.append( childs ); }); transc.attr("ng-repeat", attr.repeat); $compile(transc)(scope); // todo: access parent's var `selectedTabKey` // and make visible the related tab } }; }); 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script> <div ng-app="app"> <tabs> <!-- how to pass the attr {{item.key}} below? --> <tab key="{{item.key}}" repeat="item in items"> <!-- here some directive/expression/plain html --> {{item.value}} </tab> </tabs> </div> 

  • one
    not quite clear the logic tab . But you need to look at the required - Grundy property
  • @Grundy thanks, I'll take a closer look at this property. Logic tab is more for visual separation of logic. In each tab, respectively, will be a directive. Can there be ideas to make it easier? - kashesandr
  • one
    According to the link in my comments, the standard example with tabs, it seems to me that it is much easier than you do - Grundy
  • @Grundy super, thanks for the tips! It turned out that wanted plnkr.co/edit/IGrgb5GY5legl2ncrw2d?p=preview - kashesandr

1 answer 1

Found a solution.

Using the require property in the directive tab with the reference ^^tabs , we get access to the parent controller.

In the snippet functionality that I wanted to implement.

 (function(angular) { 'use strict'; angular.module('app', []) .run(function($rootScope){ $rootScope.items = [ {key: 1, label: 'label1', value:'content1'}, {key: 2, label: 'label2', value:'content2'}, {key: 3, label: 'label3', value:'content3'} ] }) .directive('tabsNav', function() { return { scope: { data: '=?data', id: '@for' }, replace: true, restrict: 'EA', controller: 'tabsNavCtrl', template: [ '<div>', '<div ng-repeat="item in data" ng-click="click(item.key)" ng-class="{\'-active\': item.active}">', '{{item.label}}', '</div>', '</div>' ].join('') }; }) .controller('tabsNavCtrl', function($scope, $rootScope) { if ($scope.data === null) $scope.data = []; $scope.click = function(key) { $scope.data.forEach(function(item) { item.active = item.key === key; }); return $rootScope.$broadcast('TabsClick', { key: key, id: $scope.id }); }; }) .directive('tabs', function() { return { restrict: 'E', transclude: true, scope: { id: '@' }, controller: ['$scope', function MyTabsController($scope) { var panes = $scope.panes = []; $scope.$on('TabsClick', function(e, data){ var id = data.id; var key = data.key; if ($scope.id == id) $scope.select(key); }); $scope.select = function(key){ angular.forEach(panes, function(pane) { pane.selected = pane.key == key; }); }; this.addPane = function(paneScope) { panes.push(paneScope); if (panes.length === 1) $scope.select(paneScope.key); }; }], template: '<div> <div ng-transclude></div> </div>' }; }) .directive('tab', function() { return { require: '^^tabs', restrict: 'E', transclude: true, scope: { key: '@' }, link: function(scope, element, attrs, tabsCtrl) { tabsCtrl.addPane(scope); }, template: '<div ng-show="selected"> <div ng-transclude></div> </div>' }; }); })(window.angular); 
 <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Example - example-directive-tabs-production</title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script> <script src="script.js"></script> </head> <body ng-app="app"> <tabs-nav for='id1' data="items"></tabs-nav> <tabs id="id1"> <tab key="{{item.key}}" ng-repeat="item in items"> {{item.value}} </tab> </tabs> </body> </html> 

  • one
    Write more detailed answer how exactly used require. And you can insert the final example with a snippet, just like in the question - Grundy