5
votes

I'm attempting to write my first Angular directive to add pagination functionality to my app. I'm keeping it simple for now and want to have the directive just share the scope of the controller.

In my controller, I have a scoped var called:

$scope.pages

Inside my directive's linking function, I can do:

console.dir($scope)

to see the contents of the controller's scope object, but if I try to access the pages property, it comes back as undefined.

What am I missing?

Thanks in advance.

myDirectives.directive("mdPagination", function(){
    return {
        template: '',
        restrict: 'A',
        priority: 1000,
        scope: false,
        link: function($scope, el, attrs){
            console.dir($scope.pages);  //returns undefined
            el.text('hello world');
        },
    }
});

Edit: I'm aware there's pagination modules out there, but my needs are modest and I thought building my own would be an easy way to start learning how to build directives.

3
try removing scope: falseakonsu
How is $scope.pages populated in your controller? Through an AJAX request?Mike Robinson
Check out these existing AngularJS pagination modules @ ngmodules.org/modules?query=paginationMike Pugh
Can we see your controller that sets $scope.pages and the HTML where the controller and your directive are used?Andyrooger
when is the $scope.pages is populated in the controller ? If it is populated in the controller directly it works for me. p.s. in the link function you dont need to name it $scope, the scope will be anything you pass as the first argument, name does not matter in the link function as it does in the controlleraz7ar

3 Answers

5
votes

The problem you have is directives linking functions are run before controllers are, so you typically can't access scope values during this linking phase. There are a couple other ways to do this. The most immediate way to solve your problem is with $scope.$watch. So something like this should work:

$scope.watch('pages', function(pages) {
  console.dir(pages);
});

This works just fine for lost of circumstances. I would also suggest decoupling your controller from the scope it is declared in a bit by using an attribute to pass in an expression (property name basically) for your watch. A simple example might look like this:

<div my-directive="myProperty">

link: function($scope, el, attrs) {
  $scope.watch(attrs.myDirective, function(value) {
   //do something you need to do with the value here
  });
}

However as you add complexity to your directive you may want to give your directive it's own controller to manage state without directly calling watches. This controller can either use a child scope belonging to the directive itself with scope: true or just use the parent scope with scope: false. Your choice will likely depend upon need. Then you could have:

myDirectives.directive("mdPagination", function(){
    return {
        template: '',
        restrict: 'A',
        priority: 1000,
        controller: ['$scope', '$element', '$attrs', function($scope, $element, $attrs) {
             console.dir($scope.pages);

        }],
        link: function($scope, el, attrs){
          $element.text('hello world');
        }
    }
});
-1
votes

By default, the directive shares its scope with the controller. To do that, you must not having a "scope" attribute in your object, like that:

myDirectives.directive("mdPagination", function(){
    return {
        template: '',
        restrict: 'A',
        priority: 1000,
        link: function($scope, el, attrs){
            console.dir($scope.pages);
            el.text('hello world');
        },
    }
});
-1
votes

@Sandro is right. You set the scope property in your directive to false which means that the scope will not inherit (or share) its properties with the controller. If you remove the false, it should work as you intend it.

The docs for how to use $scope are here: http://code.angularjs.org/1.2.0-rc.3/docs/api/ng.$rootScope.Scope

The developer guide for creating directives has a lot of good info about how to setup your directive so that it gives you the scope you want. Those docs are here: http://code.angularjs.org/1.2.0-rc.3/docs/guide/directive

Hope that helps.