0

I have 2 elements like so:

<div ng-hide="showDiv"></div>
<div ng-show="showDiv">
   <div directive></div>
</div>

And a directive like so:

app.directive ('directive', [
   ...
   controller: [
        '$scope',
        function ($scope) {
          $scope.accept = function () {
            $scope.showDiv = false;
          };
        }
      ],
   ....
]

I tried to use $scope.showDiv within the directive to toggle the controller but it didn't work. How do I access the controller's scope within the directive?

console.log($scope) in the directive shows $scope.showDiv === false though $scope.showDiv === true in the controller.

Ryan.lay
  • 1,741
  • 2
  • 17
  • 30
  • 2
    This is one of many cases of the most commonly misunderstood aspects of angular. `$scope.showDiv` is not an object, it is a primitive, and does not abide by the same rules for JavaScript Prototype Inheritance. This is one of the many places where the cardinal rule of angular "Always use a dot in bindings" comes into play. see http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical-inheritance-in-angularjs for a deep dive on the subject. – Claies Oct 20 '15 at 06:43
  • 2
    _sidenote_ seems you have a [wrong directive name](https://docs.angularjs.org/guide/directive#matching-directives), it should be like this: `app.directive('showMeTheDivDirective',...` – Grundy Oct 20 '15 at 06:51

2 Answers2

1

You can simply achieve this if you use controllerAs syntax.

HTML

<div ng-hide="showDiv"></div>
<div ng-show="showDiv">
   <div dir-show-div is-shown="showDiv"></div>
</div>

Directive

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

function dirShowDiv() {
   var directive = {};

   directive.scope = {
      isShown: '='
   };
   directive.controller = 'DirController';
   directive.controllerAs = 'vm';

   return directive;
}

Directive Controller

angular
    .module('app')
    .controller('DirController', DirController);

function DirController() {
   var self = this;

   self.accept = accept;

   function accept() {
      self.isShown = false;
   }
}
Knut Holm
  • 3,988
  • 4
  • 32
  • 54
  • why you move `showDiv` from `$scope` as in OP to controller? – Grundy Oct 20 '15 at 06:46
  • @Grundy I have expected OP uses it in controller as `$scope.showDiv`. I will make edit. – Knut Holm Oct 20 '15 at 06:48
  • Thank you for the answer. However I'm modifying a vendor library and this method would entail a large rewrite in my case. I've found a relatively straightforward method which I'll elaborate in an answer. Thank you once again. – Ryan.lay Oct 20 '15 at 15:04
0
$scope.showDiv = true

is a primitive value and is not inherited by the directive's scope. Assigning the value to an object allows the directive's scope to inherit the object, and any changes in the directive scope will be passed back up to the parent scope.

//controller
//change primitive to object
$scope.showDiv = {status: true};

//template
//directive names in HTML are usually in kebab case but i'm keeping it obvious for now.
//Pass showDiv object to directive
<div ng-show="showDiv.status">
    <div directive showDiv="showDiv"></div>
</div>

//directive
app.directive ('directive', [
  ...
  return {
    scope : {
       //bind directive scope to parent
       showDiv: '=showDiv'
    }
    controller: [
        '$scope',
        function ($scope) {
          $scope.foo = function () {
            //Changing object in directive will also update parent scope. 
            $scope.showDiv.status = false;
          };
        }
      ],
   ....
]

//controller
//after $scope.foo executed in directive
console.log(showDiv) === {status: false}
Ryan.lay
  • 1,741
  • 2
  • 17
  • 30