0

I have the following HTML:

<div ng-controller="MainController">
    <div class="words">
      <span ng-repeat="word in words" ng-click="setActiveWord(word)"> {{word.name}}</span>
    </div>

    <tabset>
      <tab ng-repeat="tab in tabs" heading="{{tab.title}}" active="tab.active" disabled="tab.disabled">
        {{activeWord.name}}
      </tab>
    </tabset>
</div>

Then I have a definition for the MainController which adds tabs property to the scope:

.controller('MainController', ['$scope', function($scope) {
  $scope.setActiveWord = function(word) {
    $scope.tabs[0].active = true;
  }

  $scope.tabs = [
    { title:'Dynamic Title 1', content:'Dynamic content 1' },
    { title:'Dynamic Title 2', content:'Dynamic content 2' }
  ];
}]);

Then tabset directive from here also introduces its own controller TabsetController which also defines the tabs property on the scope:

.controller('TabsetController', ['$scope', function TabsetCtrl($scope) {
  var ctrl = this,
      tabs = ctrl.tabs = $scope.tabs = [];

Which contoller's tabs property will be used for the element? Please see this Plunker for complete example.

Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488
  • That's probably because I can't formulate the question correctly because I'm not yet good at understanding Angular and it is not an easy thing to understand. But let me try to clarify. You can see that there is `MainController` and it defines`tabs` property defined on the scope, right? Now I use `tabset` bootstrap widget. And in the source code I can see that `tabset` directive requires its own `TabsetController` which also defines `tabs` property on the scope. So now I have 2 contollers which both define `tabs` property on the scope. Up until this point everything seems logical? – Max Koretskyi Jul 14 '14 at 09:39
  • 1
    tabset is a directive, hence it will have its own isolated scope which will differ from the MainController scope – V31 Jul 14 '14 at 09:44
  • Yes, agreed, they are different. The ng-repeat uses $scope.tabs from MainController. TabsetController uses its own isolated scope and defines $scope.tabs within it. They are different and used in different contexts. – Michael Kang Jul 14 '14 at 09:46
  • @V31, `tabset` indeed has its own isolated scope, so inside `TabsetController` we define `tabs` property on that isolated scope, correct? So how is it possible in the example in Plunker that when we click on the word the `MainController` sets first tab active? – Max Koretskyi Jul 14 '14 at 09:53
  • 1
    The tabset directive works by exposing an API for its child tab directives. One of the API functions is 'select' which, when called' will set the tab to active. In order for it to work, it needs to know about all its child tabs. The tab directive 'requires' the tabset directive, and registers itself with it via the TabsetController's addTab method. – Michael Kang Jul 14 '14 at 09:54
  • 1
    yup, this line: https://github.com/angular-ui/bootstrap/blob/master/src/tabs/tabs.js#L215 – kihu Jul 14 '14 at 09:56
  • @pixelbits, you wrote that `ng-repeat uses $scope.tabs from MainController` - why does it do that if `ng-repeat` is defined on the element which is a child for `tabset` element? – Max Koretskyi Jul 14 '14 at 09:57
  • I suppose then that if there is a parent div with a directive that creates it's own isolated scope it is also isolated from child elements and child directives on child divs won't have a scope that inherits from parent's isolated scope, right? – Max Koretskyi Jul 14 '14 at 10:03
  • 1
    @Maximus I'm not sure I understand. The tab element is repeated based on the model 'tabs' which is on MainController's scope. The intent is to repeat tabs (tab directive), and using an ng-repeat accomplishes that. – Michael Kang Jul 14 '14 at 10:06
  • 1
    @Maximus If a directive isolates its scope, then it is only accessible from within the directive and its template. Transcluded contents of the directive are bound to the transclusion scope which is a child of the parent scope. – Michael Kang Jul 14 '14 at 10:08
  • 2
    By the way ng-repeat creates its own child scope for each repeated element, and defines 'tab' within it. Any directives on the tab element with a lower priority than ng-repeat will be compiled and linked against the child scope. Looking at the source for tab, it runs with a priority of 0 (since not otherwise specified), and ng-repeat runs with a priority of 1000. So when ng-repeat manually compiles each tab, they are compiled against their respective child scopes and the bindings to the tab model (defined on child scope) are passed to the directive's isolated scope through the attributes. – Michael Kang Jul 14 '14 at 10:39
  • @pixelbits, thanks for you comments! It's just really hard to grasp... `The tab element is repeated based on the model 'tabs' which is on MainController's scope.` - what do you mean by `model 'tabs'` here? – Max Koretskyi Jul 14 '14 at 10:44
  • @Maximus I mean $scope.tabs = [{...}] <-- this is the model 'tabs' defined on MainController's scope. – Michael Kang Jul 14 '14 at 10:49
  • @pixelbits, ok, I think I need to break this question again into smaller pieces based on your comments. [Here is](http://stackoverflow.com/questions/24735244/ng-repeat-uses-parent-scope-which-is-separated-by-two-preceding-isolated-parent) the first thing that I don't understand. Please see. – Max Koretskyi Jul 14 '14 at 11:12

0 Answers0