0

I have a partial that I construct like this

<my-partial attr1="some text" attr2="some other text">
   <div ng-show="displayBool">
      <div>{{attr1}}</div>
      <div>{{attr2}}</div>
      <button ng-click="changeBool()">Change var</button>
</my-partial>

which renders

   <div>some text</div>
   <div>some other text</div>

In the controller I set $scope.displayBool = true. And the directive looks like this:

angular.module('grasshopperApp')
    .directive('myPartial', function () {
        return {
            restrict: 'EA',
            scope: {
                displayBool: '=',
                attr1: '@'
                attr2: '@'
            },
            templateUrl: '../my.html'
        };
    });

displayBool does not come through in the directive and the div is never shown, yet the attribute values display correctly when I inspect the hidden element in the developer panel. Why is this? How can I make that value come through?

kaveman
  • 4,339
  • 25
  • 44
1252748
  • 14,597
  • 32
  • 109
  • 229
  • Related question with some great answers: http://stackoverflow.com/questions/14050195/what-is-the-difference-between-and-in-directive-scope – kaveman Aug 27 '15 at 22:32

3 Answers3

1

You can specify a controller to your directive, and set some properties.

So you can do :

Directive

(function(){

  function directive() {
    return {
        restrict: 'EA',
        scope: {
            attr1: '@',
            attr2: '@'
        },
        templateUrl: 'template.html',
        //Declare controller for our custom directive
        controller: function($scope){
          //Set displayBool property
          $scope.displayBool = true;
        }
    };
  }

angular
  .module('app')
  .directive('myPartial', directive);

})();

Template

<div ng-show="displayBool">
   <div>{{attr1}}</div>
   <div>{{attr2}}</div>
</div>

HTML

<my-partial attr1="some text" attr2="some other text"><my-partial>

You can see Working Plunker

Paul Boutes
  • 3,285
  • 2
  • 19
  • 22
  • Are there any disadvantages to putting the controller in the directive? – 1252748 Aug 28 '15 at 15:09
  • No, the controller is defined within the context of the directive, so you can simplify your code. Moreover it can be injected into other directives in order to facilitate communication between directive. In other word, it's useful :) – Paul Boutes Aug 28 '15 at 15:18
  • Awesome knowledge! How would you share it between directives? That sounds really cool. – 1252748 Aug 28 '15 at 15:28
  • I've made an example, with master and slave directive. You can see the [Plunker](http://plnkr.co/edit/J2lPryqaulLwSeb075OO?p=preview) – Paul Boutes Aug 28 '15 at 16:52
1

Based on discussion in the comments and OP's updated code, here's a potential solution. displayBool is brought in to the directive's isolate scope using 2-way binding. We also reference the controller's $scope method changeBool using the & modifier.

Directive

angular.module('grasshopperApp')
    .directive('myPartial', function () {
        return {
            restrict: 'EA',
            scope: {
                attr1: '@',
                attr2: '@',
                changeBool: '&',
                displayBool: '='
            },
            templateUrl: '../my.html'
        };
    });

Template

 <div ng-show="displayBool">
     <div>{{attr1}}</div>
     <div>{{attr2}}</div>
     <button ng-click="changeBool()">Change var</button>
 </div>

displayBool and changeBool() here both refer to the directive's isolate scope.

Assuming a controller MyController exists, similar to:

angular.module('grasshopperApp')
    .controller('MyController', ['$scope', function($scope) {
        $scope.displayBool = true;
        $scope.changeBool = function() {
            $scope.displayBool = !$scope.displayBool;  
        }  
     }]);

You might use this directive like:

<div ng-controller="MyController">
    <my-partial 
        attr1="some text"
        attr2="some other text" 
        display-bool=displayBool
        change-bool="changeBool()">
    </my-partial>
</div>

Here display-bool is bound to MyController's $scope variable displayBool and change-bool is bound to MyController's $scope function changeBool, called, as a string.

I took this largely from the Angular dev guide on directives from the section that starts:

Next, we want to add buttons to this dialog box, and allow someone using the directive to bind their own behavior to it.

kaveman
  • 4,339
  • 25
  • 44
  • Hi. Thanks for this really detailed solution. Can you explain what the difference is between `angular.module('myApp').controller('myCtrl, ....` and and adding a controller method to the directive return? – 1252748 Aug 28 '15 at 15:08
  • I'm certainly no angular expert; I look at the difference as largely organizational. I use module-level controllers for "bigger" parts of the app - a piece of UI that may contain *multiple* directives and other behaviors. I use directive controllers when I just need a little logic - usually show/hide type stuff - for the directive to function. There is probably a more technical difference but it hasn't mattered much in my (limited) experience. – kaveman Aug 28 '15 at 16:23
0

The displayBool in your directive is an attribute and doesn't inherit from your the parent scope of your html fragment. Your directive will have to use displayBool to decide whether or not to transclude the content into your directive.

<my-partial attr1="some text" attr2="some other text" displayBool="true"></my-partial>
Jade
  • 619
  • 5
  • 13
  • But I have logic in my controller that sets it true/false based on some evaluation. How will this work with that? – 1252748 Aug 27 '15 at 22:11
  • You can bind it to your directive as a two-way bind, so when your controller changes its value, the directive's one will change too, if you set `displayBool: '='` in your directive, it should work as expected! – Gabriel Pires Aug 27 '15 at 22:14
  • @GabrielPires see the OP's code - that is exactly what he has done. – kaveman Aug 27 '15 at 22:17
  • @kaveman Yes, a `$scope` function, that I have attached to a button in the HTML template (which I added to my question), never fires. I put a console log in and nothing happens on `ng-click` – 1252748 Aug 27 '15 at 22:22
  • Yeah, he did it right in the directive js, my bad. But he still didn't set the attribute correctly, in the HTML he should set the attribute as `display-bool="{{ myBool }}"` – Gabriel Pires Aug 27 '15 at 22:25
  • @thomas well that's a whole other issue - you need to supply the scope function to the directive's isolate scope using the `&` modifier – kaveman Aug 27 '15 at 22:27
  • @GabrielPires yes, I get what you're saying now. – kaveman Aug 27 '15 at 22:29
  • @kaveman I have tried simply adding the line to my directive `closeAlert: '&',` (the name of the function) but that does not work. Do I need to do anything else? – 1252748 Aug 27 '15 at 22:31