Reputation:
I have a simple question that I think has a pretty simple solution, but somehow I am missing it.
I'm setting up a simple directive for my app. I'm leaving the scope property set to the default, "false", because I want it to share the scope of my controller.
The problem is, I can't seem to access that scope.
In my linking function, I can do:
console.dir(scope)
and I can see the property that I am after ('pages') in the scope object.
If I try to do:
console.dir(scope.pages)
however, it comes back as undefined.
What am I missing?
Thanks in advance.
MyDirectives.directive("mdPagination", function(){
return {
templateURL: "/templates/pagination.html",
replace: true,
restrict: 'A',
scope: false, //default
link: function(scope, element, attrs){
console.log('in linking function');
console.dir(scope);
console.dir(element);
console.dir(attrs);
console.dir(scope.pages);
}
}
});
The template:
<nav class="pagination" md-Pagination></nav>
The controller:
App.controller('MachinesListCtrl', function ($scope, $routeParams, $location, MachineServices, CustomerServices) {
var page = ($routeParams.page ? $routeParams.page : 1);
//if we are getting all machines based on their customer id.
if($routeParams.customerID){
MachineServices.getByCustomerId($routeParams.customerID).then(function (data) {
_.each(data.results, function (machine, index, list) {
CustomerServices.get(machine.customer_id).then(function(data){
machine.CustomerData = data.results;
});
});
$scope.Machines = data.results;
$scope.pages = data.pages;
});
}
//otherwise we just want the regular list of machines.
else{
MachineServices.query(page).then(function (data) {
_.each(data.results, function (machine, index, list) {
CustomerServices.get(machine.customer_id).then(function(data){
machine.CustomerData = data.results;
});
});
$scope.Machines = data.results;
$scope.pages = data.pages;
});
}
});
Upvotes: 3
Views: 955
Reputation: 29214
It looks like you are using angular $resource for your MachineServices, right? That creates an empty object or array for your results that you can bind to immediately that it later fills with results when the call completes asynchronously. When link
is called by angular it will not be populated with data yet.
First add logging to your query
and getByCustomerId
calls to make sure they are getting the values and setting the properties on the scope correctly. Add {{pages|json}}
somewhere in your template to see the JSON of pages as it is changed. If you see that then you can watch that property in your directive if you need to do something special when it changes:
MyDirectives.directive("mdPagination", function(){
return {
templateURL: "/templates/pagination.html",
replace: true,
restrict: 'A',
scope: false, //default
link: function(scope, element, attrs){
console.log('in linking function');
console.dir(scope);
console.dir(element);
console.dir(attrs);
console.dir(scope.pages);
// watch pages for changes
scope.$watch('pages', function(value) {
console.log("pages now has this value:");
console.dir(scope.pages);
});
}
}
});
Upvotes: 1
Reputation: 48972
The problem in your code is: MachineServices.getByCustomerId
and MachineServices.query
are asynchronous. When you call these functions, data from the server does not arrive yet and these lines
$scope.Machines = data.results;
$scope.pages = data.pages;
are not called yet.
Scope in your link function is bound to the parent's scope. But when the link
function is called, the parent's scope.pages is still undefined (due to asyn)
When we work with angular data-binding, we should be passive, just listen for changes and react accordingly(use $watch, for example), because our code does not know and should not know when the bound property has value or has its value updated. Let angular notify us the changes
Upvotes: 4
Reputation: 1035
Here is the code working with Ng 1.2:
http://jsfiddle.net/roadprophet/PfEaz/
MyDirectives.directive("mdPagination", function(){
console.log('BLAH');
return {
template: "<h1>BLAH!</h1>",
replace: true,
restrict: 'A',
scope: false, //default
link: function(scope, element, attrs){
console.log('in linking function');
console.dir(scope);
console.dir(element);
console.dir(attrs);
console.dir(scope['pages']);
}
}
});
Notice I am injecting $scope into the controller.
Upvotes: 0
Reputation: 355
Try Injecting scope into your directive.
MyDirectives.directive("mdPagination", function($scope){...
Upvotes: 0