Note that there are some explanatory texts on larger screens.

plurals
  1. POAngularJS : $scope.$watch is not updating value fetched from $resource on custom directive
    text
    copied!<p>I'm having an issue with custom directives that's driving me crazy. I'm trying to create the following custom (attribute) directive:</p> <pre><code>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); }); } } }); </code></pre> <p>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).</p> <p>I'm using it with this simple partial html:</p> <pre><code>&lt;div&gt; &lt;!-- This is actually working --&gt; &lt;ul&gt; &lt;li ng-repeat="seat in seats"&gt;{{seat.id}}&lt;/li&gt; &lt;/ul&gt; &lt;!-- This is not... --&gt; &lt;div style="border: 1px dotted black" seat-map&gt;&lt;/div&gt; &lt;/div&gt; </code></pre> <p>And this is the controller which is loading the scope:</p> <pre><code>function SeatsCtrl($scope, Seats) { $scope.sessionId = "12345"; $scope.zoneId = "A"; $scope.seats = Seats.query({sessionId: $scope.sessionId, zoneId: $scope.zoneId}); $scope.max_seats = 4; } </code></pre> <p>Where "Seats" is a simple service using $resources to fetch a JSON from the server</p> <pre><code>angular.module('myApp.services', ['ngResource']) .factory('Seats', function($resource){ return $resource('json/seats-:sessionId-:zoneId.json', {}, {}); }) ; </code></pre> <p>app.js (asientos_libres.html is the partial I've been using):</p> <pre><code>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'}); }]); </code></pre> <p>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").</p> <p>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...</p> <p>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.</p> <p><em>Note: The updateSeatInfo is just a test function, the actual function I'll use is a bit more complex.</em></p> <p>Any idea about how to cope with it?</p> <p>Thank you a lot beforehand!</p> <p><strong>Edit 1:</strong> 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.</p> <p><strong>Edit 2: Solved!(?)</strong> 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 <a href="http://docs.angularjs.org/api/ng.$timeout" rel="noreferrer">http://docs.angularjs.org/api/ng.$timeout</a>, we can use $timeout (a wrapper over setTimeout) <strong>with no delay</strong>! 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.</p> <p>Hope it will work for long-wait requests, too...</p> <p>If someone knows a better way to fix it, please tell!</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload