valkirilov
valkirilov

Reputation: 1853

AngularJS - How to access $scope from a directive with specified scope

I have a custom directive which has got it's own scope which accepts values from the directive's DOM attributes but there are a few vars from the $scope which I want to access from the directive too. Can anyone help me to do this.

Here is my directive and how I use it.

appDirectives.directive('appTemplate', function () {
    return {
        restrict: 'E',
        templateUrl: 'partials/templates/template.html',
        scope: {
            template: '='
        },
    }
});
<div ng-repeat="template in templates" ng-click="chooseTemplate(template)">
    <app-template template="template"></app-template>
</div> 

And this is the template of the directive and here I have template value but I want also to access $scope.rootPath

<div class="template">
    {$ ???scope.rootPath??? $}
    {$ template is accesable $}    
</div> 

Upvotes: 1

Views: 197

Answers (4)

Kos Prov
Kos Prov

Reputation: 4293

Another option is to have appTemplate prototypally inherit from the parent scope and use $parse for the template attribute.

app.directive('appTemplate', ['$parse', function($parse) {
  return {
    restrict: 'E',
    templateUrl: 'template.html',
    link: function(scope, elem, attrs) {
      var templateGet = $parse(attrs.template);
      scope.$watch(templateGet, function(value) {
        scope.template = value;
      });
    }
  };
}]);

It sees all variables from the outtermost scope (templates, rootPath etc) but does not really depend on the name of the iteration variable in the ng-repeat. So both this:

<div ng-repeat="template in templates">
  <app-template template="template"></app-template>
</div>

and this:

<div ng-repeat="t in templates">
  <app-template template="t"></app-template>
</div>

works without any modification.

Caveats:

  1. If ng-repeat is defined as ng-repeat="t in templates" just because you already have a variable called template which is needed in the children scopes, you are effectively doomed because appTemplate overrides it internally (this does not affect parent variable, whatsoever)
  2. If appTemplate is meant to edit data that have been inherited, those data have to be at least a 2nd level property (customer.firstName, not firstName). This is a general caveat with scope inheritance.

Working plunker.

Upvotes: 1

valkirilov
valkirilov

Reputation: 1853

It appears that you don't have to declare local scope for the directive, the attributes are accessible without it. After omitting the scope declaration it will work, and the directive will look like this:

appDirectives.directive('appTemplate', function () {
    return {
        restrict: 'E',
        templateUrl: 'partials/templates/template.html',
        transclude: true
    }
});

The other way, which will also work, is to inject the $scope.rootPath to the directive as a parameter.

Upvotes: 1

Yaniv Efraim
Yaniv Efraim

Reputation: 6713

You can use is with isolated scopes as well:

appDirectives.directive('appTemplate', function () {
    return {
        restrict: 'E',
        templateUrl: 'partials/templates/template.html',
        scope: {
            template: '=',
            rootPath: '='
        },
    }
});
<div ng-repeat="template in templates" ng-click="chooseTemplate(template)">
    <app-template template="template" root-path="rootPath"></app-template>
</div> 

… and then access it as usual:

<div class="template">
    {$ rootPath is accesable $}
    {$ template is accesable $}    
</div> 

There are probably other solutions but this should work for you.

Upvotes: 4

Sten Muchow
Sten Muchow

Reputation: 6701

The is exactly how you go about passing objects into a isolate scope. If your controller is in the parent of your directive then the directive will inherit the functionality of the controller.

Unless you need it to have an isolated scope, for example each template in templates has their own unique values then you can pass it in as an object like you are doing now.

Upvotes: 1

Related Questions