Angularjs passing object to directive

56,903

Solution 1

Since you are using $resource to obtain your data, the directive's link function is running before the data is available (because the results from $resource are asynchronous), so the first time in the link function scope.walks will be empty/undefined. Since your directive template contains {{}}s, Angular sets up a $watch on walks, so when the $resource populates the data, the $watch triggers and the display updates. This also explains why you see the walks data in the console -- by the time you click the link to expand the scope, the data is populated.

To solve your issue, in your link function $watch to know when the data is available:

scope.$watch('walks', function(walks) {
   console.log(scope.walks, walks);
})

In your production code, just guard against it being undefined:

scope.$watch('walks', function(walks) {
  if(walks) { ... }
})

Update: If you are using a version of Angular where $resource supports promises, see also @sawe's answer.

Solution 2

you may also use

scope.walks.$promise.then(function(walks) {
    if(walks) {
      console.log(walks);
    }
  });

Solution 3

Another solution would be to add ControllerAs to the directive by which you can access the directive's variables.

app.directive('walkmap', function() { 
  return {
    restrict: 'A',
    transclude: true,
    controllerAs: 'dir',
    scope: { walks: '=walkmap' },
    template: '<div id="map_canvas"></div>',
    link: function(scope, element, attrs)
    {
      console.log(scope);
      console.log(scope.walks);
    }
  };
});

And then, in your view, pass the variable using the controllerAs variable.

<div walkmap="store.walks" ng-init="dir.store.walks"></div>

Solution 4

Try:

<div walk-map="{{store.walks}}"></div>

angular.module('app').directive('walkMap', function($parse) {
  return {
    link: function(scope, el, attrs) {
      console.log($parse(attrs.walkMap)(scope));
    }
  }
});
Share:
56,903
winkerVSbecks
Author by

winkerVSbecks

finder of new ways to confuse myself

Updated on April 13, 2020

Comments

  • winkerVSbecks
    winkerVSbecks about 4 years

    Angular newbie here. I am trying to figure out what's going wrong while passing objects to directives.

    here's my directive:

    app.directive('walkmap', function() { 
      return {
        restrict: 'A',
        transclude: true,
        scope: { walks: '=walkmap' },
        template: '<div id="map_canvas"></div>',
        link: function(scope, element, attrs)
        {
          console.log(scope);
          console.log(scope.walks);
        }
      };
    });
    

    and this is the template where I call the directive:

    <div walkmap="store.walks"></div>
    

    store.walks is an array of objects.

    When I run this, scope.walks logs as undefined while scope logs fine as an Scope and even has a walks child with all the data that I am looking for.

    I am not sure what I am doing wrong here because this exact method has worked previously for me.

    EDIT:

    I've created a plunker with all the required code: http://plnkr.co/edit/uJCxrG

    As you can see the {{walks}} is available in the scope but I need to access it in the link function where it is still logging as undefined.