I'm having an issue with custom directives that's driving me crazy.
I'm trying to create the following custom (attribute) directive:
angular.module('componentes', [])
.directive("seatMap", function (){
return {
restrict: 'A',
link: function(scope, element, attrs, controller){
function updateSeatInfo(scope, element){
var txt = "";
for (var i in scope.seats)
txt = txt + scope.seats[i].id + " ";
$(element).text("seat ids: "+txt);
}
/*
// This is working, but it's kind of dirty...
$timeout(function(){updateSeatInfo(scope,element);}, 1000);
*/
scope.$watch('seats', function(newval, oldval){
console.log(newval, oldval);
updateSeatInfo(scope,element);
});
}
}
});
This "attribute-type" directive (called seatMap) is trying to show a list of seat ids (e.g, for a theatre) which I'll fetch from the server via $resource service (see code below) into a div (element).
I'm using it with this simple partial html:
<div>
<!-- This is actually working -->
<ul>
<li ng-repeat="seat in seats">{{seat.id}}</li>
</ul>
<!-- This is not... -->
<div style="border: 1px dotted black" seat-map></div>
</div>
And this is the controller which is loading the scope:
function SeatsCtrl($scope, Seats) {
$scope.sessionId = "12345";
$scope.zoneId = "A";
$scope.seats = Seats.query({sessionId: $scope.sessionId, zoneId: $scope.zoneId});
$scope.max_seats = 4;
}
Where "Seats" is a simple service using $resources to fetch a JSON from the server
angular.module('myApp.services', ['ngResource'])
.factory('Seats', function($resource){
return $resource('json/seats-:sessionId-:zoneId.json', {}, {});
})
;
app.js (asientos_libres.html is the partial I've been using):
angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives', 'componentes']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/view1', {templateUrl: 'partials/asientos_libres.html', controller: SeatsCtrl});
$routeProvider.otherwise({redirectTo: '/view1'});
}]);
The problem is, even though I set up a "scope.$watch" in the link function of the directive so that the scope can check whether "seats" attribute has changed to update the list of ids, it isn't working at the moment $scope.seats is changing in the controller (when we call "query").
As you might see in the code, I made a try using $timeout to delay the launch of "updateSeatInfo", but I'm afraid it's not the smartest solution by far...
I also tried to not to make a JSON request, but use a hard-coded dictionary in $scope.seats and it works, so it seems it's a matter of synchrony.
Note: The updateSeatInfo is just a test function, the actual function I'll use is a bit more complex.
Any idea about how to cope with it?
Thank you a lot beforehand!
Edit 1: Added app.js, where I'm using router to call SeatsCtrl, thanks to Supr for the advice. However, I'm still having the same issue.
Edit 2: Solved!(?)
Ok! It seems I found a solution, which may not be the best, but it's working properly! :)
As far as I could see here http://docs.angularjs.org/api/ng.$timeout, we can use $timeout (a wrapper over setTimeout) with no delay! This is great because we aren't artificially delaying the execution of our code inside $timeout, but we're making the directive not to run it until the asynchronous request has finished.
Hope it will work for long-wait requests, too...
If someone knows a better way to fix it, please tell!
See Question&Answers more detail:
os