Обертка директивы angular -ui tabset и столкновение с ошибками "Несколько директив с запросом на исключение/изолированный объем"

Я пытаюсь расширить функциональность табуляции angular -ui, и у меня возникают проблемы с ее упаковкой.

Этот плункер - это директива tabset, не обернутая:

http://plnkr.co/edit/AhG3WVNxCal5fZOUbSu6?p=preview

Этот плункер содержит мою первую попытку обернуть директиву tabset:

http://plnkr.co/edit/naKXbeVOS8nizwDPUrkT?p=preview

Первоначальный метод обертывания - это прямолинейная упаковка. Но... Я вводил дополнительные div в шаблон замены, чтобы избежать ошибок "Несколько директив с запросом на выделенную область видимости" и "Несколько директив с просьбой о переходе" angular и убедиться, что выключение происходит.

Key code фрагменты:

.directive('urlTabset', function() {
  return {
    restrict: 'E',
    transclude: true,
    replace: true,
    scope: {
      tabManager: '='
    },
    controller: [ "$scope", function($scope) {
      var tabManager = $scope.tabManager;
    }],
    template:
      '<div>' +
        '<tabset>' +
          '<div ng-transclude>' +
          '</div>' +
        '</tabset>' +
      '</div>'
  };
})

.directive('urlTab', function() {
  return {
    require: '^urlTabset',
    restrict: 'E',
    transclude: true,
    replace: true,
    scope: { tabName: '@' },
    link: function(scope, element, attrs, urlTabsetCtrl) {
    },
    template:
      '<div>' +
        '<tab>' +
          '<div ng-transclude>' +
          '</div>' +                  
        '</tab>' +
      '</div>'
  };
});

Однако, я думаю, что дополнительные div в шаблоне вызывают проблемы. Вот развернутый таблеток с дополнительными div в тех местах, где мой шаблон добавит их.

http://plnkr.co/edit/kjDs7xJcZqltCAqUSAmX?p=preview

Итак, логично уничтожить divs... но здесь мне нужна помощь. Кто-нибудь знает о чистом способе сделать это, не нажимая ошибки "Несколько директив с просьбой об изолированной области видимости" и "Несколько директив с просьбой о переходе" angular. Вот одна неудачная попытка.

http://plnkr.co/edit/0C6lFNhfdTVcF7ahuN3G?p=preview

Error: Multiple directives [urlTab, tab] asking for transclusion on: <tab class="ng-isolate-scope ng-scope">

Кстати, если вам интересно, что я пытаюсь сделать, конечной целью является использование атрибута tabManager, переданного в urlTabset, для автоматического заполнения полей в директиве tab (завернутый urlTab). Чтобы быть более конкретным, это то, к чему я стремился:

.directive('urlTab', function() {
  return {
    require: '^urlTabset',
    restrict: 'E',
    transclude: true,
    replace: true,
    scope: { tabName: '@' },
    link: function(scope, element, attrs, urlTabsetCtrl) {
      scope.tabs = urlTabsetCtrl.tabs;
      scope.tabSelected = urlTabsetCtrl.tabSelected;
    },
    template:
      '<tab active="tabs[tabName].active" disabled="tabs[tabName].disabled" select="tabSelected(tabName)" ng-transclude>' +
      '</tab>'
  };
});

Шаблон выше явно не работает, но он дает вам суть того, что я пытаюсь сделать.

И я в порядке с решением, для которого директива wrapping не имеет изолированной области. Я могу обойти это, сохранив состояние в контексте контроллера.

Ответ 1

Если вы пытаетесь расширить функциональность angular-ui, вам может быть лучше сделать это с директивами атрибутов, а не с новыми элементами. Возможно, я ошибаюсь, но похоже, что вы не собираетесь изменять общую структуру DOM, кроме как заменить свою директиву на angular -ui. Например, используя HTML

<tabset url-tabset>
    <tab url-tab>
        <tab-heading>
            <i class="icon-list"></i> Details
        </tab-heading>
        Details content.
    </tab>
    <tab url-tab>
        <tab-heading>
            <i class="icon-thumbs-up"></i> Impact
        </tab-heading>
        Impact tab content.
    </tab>                    
</tabset>

означает, что вам больше не нужно выполнять замену закладок или шаблонов. Это позволит избежать этой проблемы вместе.

Это оставляет проблему изолированного объема атрибутов, которые вы хотите использовать для увеличения. Вместо этого вы можете использовать scope: true для захвата той же выделенной области, что и tab и tabset (хотя вы не можете определить привязки здесь), и вы можете получить атрибуты, так как вы использовали бы обычные значения привязки, используя $parse и attrs.

Ваши директивы (с функциональностью вашего второго плункера) в конечном итоге выглядят примерно так.

angular.module('plunker', ['ui.bootstrap'])

.directive('urlTabset', function() {
  return {
    restrict: 'A',
    require: 'tabset', // Confirm the directive is only being used on tabsets
    controller: [ "$scope", "$attrs", function($scope, $attrs) {
      var tabManagerGetter = $parse($attrs.tabManager); // '='
      this.getTabManager = function() {
        return tabManagerGetter($scope);
      };

      // fun stuff here
    }]
  };
})

.directive('urlTab', function() {
  return {
    require: ['tab', '^urlTabset'],
    restrict: 'A',
    link: function(scope, element, attrs, ctrls) {
      var urlTabsetCtrl = ctrls[1];

      function getTabName() {
        return attrs.tabName; // '@'
      }

      var tabManager = urlTabsetCtrl.getTabManager();

      // fun stuff here
    }
  };
});