2

I have the following HTML:

<ng-view>
    <tabset>
        <tab>
            <tab-heading>
                <i class="glyphicon glyphicon-info-sign"></i>
            </tab-heading>
            <div>
                <div>
                    <div>{{selectedWord.translation}}</div>
                </div>
    ...
</ng-view>

And the controller which is loaded for the view:

angular.module('app').controller('SampleController', function ($scope) {
    $scope.selectedWord = {translation: '[te]'};
}

The directive ng-view creates a new scope which I presume then is injected into the SampleController constructor as a parameter.

tabset creates its own isolated scope so it doesn't inherit properties from the scope created by the ng-view.

.directive('tabset', function() {
  return {
    restrict: 'EA',
    transclude: true,
    replace: true,
    scope: {
      type: '@'
    },

Each tab directive also creates its own scope which also is not inherited from the scope created by the tabset directive.

.directive('tab', ['$parse', function($parse) {
  return {
    require: '^tabset',
    restrict: 'EA',
    replace: true,
    templateUrl: 'template/tabs/tab.html',
    transclude: true,
    scope: {
      active: '=?',
      heading: '@',
      onSelect: '&select', //This callback is called in contentHeadingTransclude
                          //once it inserts the tab's content into the dom
      onDeselect: '&deselect'
    },

What I don't understand is why it is possible to access the property selectedWord.translation defined in the scope created by the ng-view directive from inside the scope created by the tab directive (which is isolated scope itself and is preceded by the isolated scope created by the tabset) ?

Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488

1 Answers1

2

When a directive uses transclusion, it creates a child scope for the transcluded contents (sometimes also referred to as transclusion scope). When a directive also defines an isolated scope, there are actually two scopes being used in the same directive:

  1. Transclusion Scope - bound to the transcluded contents
  2. Isolated Scope - bound to your template (if defined) or available as a private scope for your directive.

So the reason that selectedWord is resolvable is because the transcluded contents are bound to the transclusion scope of ngView. And the transclusion scope of any directive is just a child scope that prototypically inherits scope from its parents.

This is true of any directive that uses transclusion:

Example

<!-- name defined in parent scope -->
<div ng-init="name='test'">
    <!-- ng-if creates a child scope for its transcluded contents
       The child scope prototypically inherits scope from its parents -->
    <div ng-if="true">
        <!-- this is the transcluded contents for ng-if -->
        <div> 
            <my-dir-using-isolate-scope>
               <!-- this is the transcluded contents for 
                    my-dir-using-isolate-scope directive --> 
               {{ name }} 
            </my-dir-using-isolate-scope>
        </div>
    </div>
</div>
Michael Kang
  • 52,003
  • 16
  • 103
  • 135
  • Thanks! Do you know any good resource besides the `docs.angularjs.org` where there is a good explanation about transcluded scopes? – Max Koretskyi Jul 12 '14 at 15:17
  • Where is or how is `transcluded contents` defined? – Max Koretskyi Jul 12 '14 at 15:20
  • 1
    Whenever you have contents inside of a element that has a directive - *that is* the tanscluded contents. There's nothing special about transclusion scope. Its just a child scope. A directive with a template will overwrite the transcluded contents with its template. But then you can also link the transcluded contents into your template by applying the ng-transclude directive inside your template. – Michael Kang Jul 12 '14 at 15:21
  • Thanks a lot for the elaborate answer! I've also found [this](http://stackoverflow.com/questions/20656168/angularjs-directives-isolated-scope-and-inherited-scope?rq=1) question and answer - does it have anything to do with transcluded contents? I'd assume that `Inside isolated scope directive: {{myProperty}}` is a transcluded contents inside `my-inherit-scope-directive` directive and so it gets access to `myProperty` through a transcluded scope? – Max Koretskyi Jul 12 '14 at 15:41
  • Ah, I'm smart :)))... thanks! :) The guy didn't explicitly stated that directive is `transcluded`, so I guess it is set to `true` by default? – Max Koretskyi Jul 12 '14 at 15:53
  • Hey, can you please check my [this](http://stackoverflow.com/questions/24726335/how-can-i-select-a-tab-from-outside-controller) post? Thanks! – Max Koretskyi Jul 14 '14 at 08:51
  • There is no transclusion happening in that post. Transclusion only applies when you have a template. But it still true that the contents under the directive are compiled and linked against the outer scope (outside of the directive). – Michael Kang Jul 14 '14 at 08:58
  • Thanks. Yes, I know there is no transclusion there. I just can't figure out how I can switch tabs from outer controller? – Max Koretskyi Jul 14 '14 at 09:04
  • Maybe post another question? – Michael Kang Jul 14 '14 at 09:05
  • Yeah, I did. It's [here](http://stackoverflow.com/questions/24726335/how-can-i-select-a-tab-from-outside-controller). Or do you mean another one besides this one? – Max Koretskyi Jul 14 '14 at 09:07
  • It seems you have more questions in addition to this one. Its more likely you'll get an answer by posting another question rather than asking it in a comment. I'm sure these additional comments will confuse the answer to this one. – Michael Kang Jul 14 '14 at 09:10