nathasm
nathasm

Reputation: 2564

Directive behavior changes when defining isolated scope

I have a directive for a javascript grid library slickgrid.

http://plnkr.co/edit/KWZ9i767ycz49hZZGswB?p=preview

What I want to do is pass the selected row back up the controller. So I want to use isolated scope (using the '=') to get two-way binding working between the controller and directive.

Everything works if I define the directive without any sort of scope declaration:

<slickgrid id="myGrid" data="names" selected-item="selectedItem"></slickgrid>

app.directive('slickgrid', function() {
  return {
  restrict: 'E',
  replace: true,
  //scope: {
  //  selectedItem: '='
  //},
  template: '<div></div>',
  link: function($scope, element, attrs) {
   ...
    var redraw = function(newScopeData) {
    grid.setData(newScopeData);
    grid.render();
};
$scope.$watch(attrs.data, redraw, true);

But if I uncomment the lines above (lines 19-21 in app.js) it looks like the $scope.$watch which is watching the attrs.data object is calling redraw but the attrs.data is being passed in as undefined.

My analysis could be wrong, but I'm not sure why defining the scope would cause this. Can someone explain why that might be?

.nathan.

Upvotes: 1

Views: 288

Answers (1)

Mark Rajcok
Mark Rajcok

Reputation: 364677

If you define an isolate scope, then any $watch in your directive will be looking for whatever attrs.data evaluates to on your isolate scope. attrs.data evaluates to the string names, so the $watch is looking for $scope.names on your isolate scope, which doesn't exist. (Without the isolate scope, the directive uses the same scope as MainCtrl, and $scope.names exists there.)

To use an isolate scope, you'll need to define another isolate scope property to pass in names:

scope: {
  selectedItem: '=',
  data: '='
},
...
$scope.$watch('data', redraw, true);

The HTML can remain the same.

Upvotes: 1

Related Questions