Search code examples
angularjsangularjs-directiveangularjs-scope

Share variable between components angular 1.5


I have an angular component setup like this:

(function(angular) {
'use strict';
angular.module('bar', [])
angular.module('bar').component('bar', {
template: '<h1 ng-show="showMe">It worked</h1>',
bindings: {
  showMe: '='
   }
 });
})(window.angular);

and another setup like this

(function(angular) {
'use strict';
angular.module('foo', [])
angular.module('foo').component('foo', {
template: '<button ng-click="showMe = true">Click Me</button>' +
        '<bar showMe = "showMe"></bar>'
});
})(window.angular);

my index.html

<foo>Hello Plunker!</foo>

But I cannot get the template in bar to work. What am I missing?

I have a plunkr here: https://plnkr.co/edit/Qj9ZL9NFtdXWHBY0yzJf?p=preview


Solution

  • I suspect that you are fighting the fact that component scopes are always isolate (so access to parent scope only exists if you declare the binding)

    I suspect your code would need to look something like this:

    <foo newPopup="'something'">
      <!-- bar inside foo's template -->
      <bar newPopup="$ctrl.newPopup"></bar>
      <!-- end foo's template -->
    </foo>
    

    Directives give access to the parent scope by default, which might explain why it works as a directive for you in inner component (probably bar) would get access to the parent $ctrl (since directives don't set controllerAs by default either).

    EDIT: I still think my original answer is true and with directives this was working with scope fall through. There are a couple other fixes (2 and three below) in the plnkr which I am guessing are unrelated to the original issue, because if they were I can't imagine it would have worked as a directive either.

    Making the following changes should make your plunk work:

    1. Whenever you refer to a scope variable in a component, prefix it with $ctrl (or whatever your controllerAs value is for that component $ctrl is the default in a component where not having controllerAs syntax is the default for directives).
    2. Make the foo module depend on bar (it is consuming it so it must depend on it)
    3. When refering to camelBack scope (for directives) or binding (for components) values in the template change capitals to lowercase and add a dash (e.g. camelBack -> camel-back)

    https://plnkr.co/edit/ka2owI?p=preview

    foo.js

    (function(angular) {
      'use strict';
      angular.module('foo', ['bar'])
      angular.module('foo').component('foo', {
      template: '<button ng-click="$ctrl.showMe = true">Click Me</button>' +
                '<bar show-me = "$ctrl.showMe"></bar>'
    });
    })(window.angular);
    

    bar.js

    (function(angular) {
      'use strict';
      angular.module('bar', [])
      angular.module('bar').component('bar', {
        template: '<h1 ng-show="$ctrl.showMe">It worked</h1>',
        bindings: {
          showMe: '='
        }
      });
    })(window.angular);
    

    For further clarity (because $ctrl is used twice above and in the plunk making its usage appear ambigious), you can have seperate controllerAs values here and foo's should not be accessible in bar. foo.js and bar.js could just as reasonably be as follows and this would still work:

    foo.js

    (function(angular) {
      'use strict';
      angular.module('foo', ['bar'])
      angular.module('foo').component('foo', {
      controllerAs: 'fooCtrl',
      template: '<button ng-click="fooCtrl.showMe = true">Click Me</button>' +
                '<bar show-me = "fooCtrl.showMe"></bar>'
    });
    })(window.angular);
    

    bar.js

    (function(angular) {
      'use strict';
      angular.module('bar', [])
      angular.module('bar').component('bar', {
        controllerAs: 'barCtrl',
        template: '<h1 ng-show="barCtrl.showMe">It worked</h1>',
        bindings: {
          showMe: '='
        }
      });
    })(window.angular);