Nathaniel Johnson
Nathaniel Johnson

Reputation: 4839

Angular Scope within Directives

Given this fairly simple angular wrapper for a JQuery UI button:

angular.module('Sample.controllers', [])
  .controller('mainController', ['$scope',
    function($scope) {
      $scope.jump =  function () {alert("jump");};
   }])
  .directive('jquiwButton', function() {
    return {
      scope: {},
      restrict: 'A',
      replace:true,
      link: function(scope, element, attrs) {
        var options = {};
        if (angular.isDefined(attrs["jquiDisabled"])) {
          options.disabled = attrs["jquiDisabled"];
        }

        if (angular.isDefined(attrs["jquiIconPrimary"])) {
          if (!angular.isDefined(options.icons.primary)) {
            options.icons ={};
          }
          options.icons.primary = attrs["jquiIconPrimary"];
        }

        if (angular.isDefined(attrs["jquiIconSecondary"])) {
          if (!angular.isDefined(options.icons.secondary)) {
            options.icons ={};
          }
          options.icons.secondary = attrs["jquiIconSecondary"];
        }

        if (angular.isDefined(attrs["jquiLabel"])) {
          options.label = attrs["jquiLabel"];
        }

        if (angular.isDefined(attrs["jquiText"])) {
          options.text = attrs["jquiText"];
        }

        element.button(options);
      }
    };
  });
  angular.module('Sample', ['Sample.controllers']);  

And the markup.

<body ng-controller="mainController"> 
  <button jquiw-button jqui-label="Hello" ng-click="jump()">Hello</button>
</body>

and it works fine until I add a scope at which point I lose the ability to use the standard angular bindings to the outer scope. In my case the markup `ng-click='jump()' now won't work because it can't find the method jump which is defined in the outer context and not in the isolate scope. Now I know that I can specifically bind ng-click back to the outer scope but I want to avoid doing that since it requires knowledge of all the possible directives I might need to bind.

So my question is: How do I let other directives work in the outer scope while still having an isolate scope?

plunker: http://plnkr.co/edit/eRoOeq?p=preview

Remove line 8: scope: {}, and it ng-click calls the correct function.

Upvotes: 0

Views: 224

Answers (2)

Adam
Adam

Reputation: 5236

You can reference a function in the parent scope from inside the isolate scope by using the & binding. This is the proper way to call a function from an isolate scope inside a directive according to the directive documentation.

I created a working CodePen example to demonstrate it working flawlessly.

Here's the relevant parts:

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

app.controller('MainCtrl', function($scope) {
  $scope.jump = function() {
    alert('jump called');
  };
});

app.directive('myDirective', function() {
  return {
    restrict: 'E',
    scope: {
      call: '&'
    },
    link: function postLink(scope, element, attrs) {
      scope.call();
    }
  };
});

and in the template:

<section ng-app="app" ng-controller="MainCtrl">
  <my-directive call="jump()"></my-directive>
</section>

I hope this helps.

Upvotes: 1

zs2020
zs2020

Reputation: 54504

Use ng-click="$parent.jump()".

Upvotes: 2

Related Questions