hsz
hsz

Reputation: 152294

Access directive from the same scope

I have created a custom directive with method defined:

app.directive('modal', function() {
  return {
    restrict: 'E',
    template: '<div class="modal" ng-show="visible">modal box</div>',
    scope: {
      ngModel: '='
    },
    link: function(scope, element, attrs) {
      scope.visible = false;
      scope.show = function () {
        this.visible = true;
      };
      scope.close = function () {
        this.visible = false;
      };
    }
  };
});

I'm using it like:

<button ng-click="modal.show()">Show modal</button>
<modal></modal>

However I cannot access this modal directive in the same scope.

I've tried with defined id attribute, like:

<button ng-click="myModal.show()">Show modal</button>
<modal id="myModal"></modal>

Is it even possible to access directive scope this way ?

Or better way would be do it using $rootScope or broadcasting events ?

I would like to not define this directive in controller - controller should not know about its existence.

Upvotes: 0

Views: 77

Answers (4)

okanozeren
okanozeren

Reputation: 555

Your view might be like below:

<button ng-click="showModal()">Show modal</button>
<modal></modal>

You can put your methods to the $rootScope apart from the isolated scope. Only the template uses it's isolated scope and variables defined on it.

Here is a modified example:

app.directive('modal', function ($rootScope) {
    return {
        restrict: 'E',
        template: '<div ng-show="visible">modal box</div>',
        scope: {},
        link: function (scope, element, attrs) {
            scope.visible = false;
            $rootScope.showModal = function () {
                console.log("showModal");
                scope.visible = true;
            };
            $rootScope.closeModal = function () {
                console.log("closeModal");
                scope.visible = false;
            };
        }
    };
});

Upvotes: 0

Sulthan
Sulthan

Reputation: 130191

You found a problem in your architecture. It's true that there are workarounds but they only make the problem more complicated.

If you look for a stable solution, check out the code for $modal in Angular Bootstrap. You will see they have $modal as a service.

The reasons are (for example) the following:

  1. Opening and closing can be done from any scope
  2. Template for the modal is separated from other code.

Upvotes: 1

user1817574
user1817574

Reputation:

I would go with events:

var myApp = angular.module('myApp',[]);

function MyCtrl($scope) {
    $scope.showModal = function(){
        $scope.$parent.$broadcast("show-modal");
    };

    $scope.hideModal = function(){
        $scope.$parent.$broadcast("hide-modal");
    };
}

myApp.directive('modal', function() {
  return {
    restrict: 'E',
    template: '<div class="modal" ng-show="visible">modal box</div>',
    link: function(scope, element, attrs) {
      scope.visible = false;
      scope.$on('show-modal', function(){
          scope.visible = true;
      });

      scope.$on('hide-modal', function(){
          scope.visible = false;
      });
    }
  };
})

Basically: broadcast an event (either 'show' or 'hide') from your controller, catch it inside the directive and do your logic.

And your html template:

<div ng-controller="MyCtrl" ng-app="myApp">
  <button ng-click="showModal()">Show modal</button>
    <br/>
    <button ng-click="hideModal()">Hide modal</button>
  <modal></modal>
</div>

Upvotes: 0

Theodore Yankov
Theodore Yankov

Reputation: 369

Parent controllers have access to their child directives' scopes.

Here I've created a small example to illustrate what I'm saying. Unless you have the scope attribute in your directive, it will use its parent's scope.

Upvotes: 0

Related Questions