Function called before filling the $ scope array

I have a problem with AngularJS and a function that is called before populating the data array. When my function is called in ng-init , the $scope.bookings array was not evaluated (filled with data), resulting in no data.

My goal: to receive all orders for a certain type of reservation and a certain date and display them all in <td>

http://i.imgur.com/GpjemTI.png


Here is my HTML code:

Description: I look through all bookingTypes , and then through all dates . ng-init is executed as many times as dates, and it works. otherBookings should be an array of orders for this bookingType and this date. However, $scope.bookings not populated with data, so the otherBookings never runs.

 <tr ng-repeat="bookingType in bookingTypes"> <td>{{bookingType.Name}}]</td> <td ng-repeat="date in dates" ng-init="otherBookings = checkOtherBookings(bookingType.ID, date)"> <span ng-repeat="otherBooking in otherBookings"> <a ng-href="/Bookings/Edit/{{otherBooking.Booking.ID}}"><span >{{otherBooking.Customer.FirstName}}</span></a> </span> </td> </tr> 

Here is my JavaScript code:

Description: At the top of the BookingsController I call a service that populates the $scope.bookings array $scope.bookings data, and the $scope.checkOtherBookings() function is below:

 BookingService.getAllBookings().then(function(data) { $scope.bookings = data.data; }); $scope.checkOtherBookings = function(bookingType, date) { console.log($scope.bookings); var newBookingArray = []; for(var i = 0; i < $scope.bookings.length; i++) { if($scope.bookings[i].Booking.Type == bookingType) { var tmpDateFrom = $scope.bookings[i].Booking.DateFrom; var tmpDateTo = $scope.bookings[i].Booking.DateTo; if(date >= tmpDateFrom && date <= tmpDateTo) { newBookingArray.push($scope.bookings[i]); } } } return newBookingArray; }; 

The $scope.checkOtherBookings() function is called 22 times (as many times as the dates), but console.log($scope.bookings) outputs 22 times [] - so my observation is that the $scope.bookings empty every time when the function is called.

I need some kind of wait method to execute ng-init until the $scope.bookings array is filled with data.

Any ideas?


UPDATE 1 - 09/14/13

Now newBookingArray has some data, but otherBookings in ng-init never get it.

HTML:

 <tr ng-repeat="bookingType in bookingTypes"> <td>{{bookingType.Name}}</td> <td ng-repeat="date in dates" ng-init="otherBookings = checkOtherBookings(bookingType.ID, date)"> <span ng-repeat="otherBooking in otherBookings"> <a ng-href="/Bookings/Edit/{{otherBooking.Booking.ID}}"><span >{{otherBooking.Customer.FirstName}}</span></a> </span> </td> </tr> 

JavaScript:

 BookingService.getAllBookings().then(function(data) { $scope.bookings = data.data; }); $scope.checkOtherBookings = function(bookingTypeID, date) { var deferred = $q.defer(); $scope.$watch('bookings', function(bookings) { if(!bookings.length) return; var newBookingArray = []; for(var i = 0; i < $scope.bookings.length; i++) { if($scope.bookings[i].Booking.Type == bookingTypeID) { var tmpDateFrom = $scope.bookings[i].Booking.DateFrom; var tmpDateTo = $scope.bookings[i].Booking.DateTo; if(date >= tmpDateFrom && date <= tmpDateTo) { newBookingArray.push($scope.bookings[i]); console.log(JSON.stringify(newBookingArray)); } } } deferred.resolve(newBookingArray); }); return deferred.promise; }; 

UPDATE 2 - 09/14/13

It is allowed! I have moved the assignment from ng-init to ng-repeat and it works fine.

HTML:

 <tr ng-repeat="bookingType in bookingTypes"> <td>{{bookingType.Name}}</td> <td ng-repeat="date in dates"> <span ng-repeat="otherBooking in checkOtherBookings(bookingType.ID, date)"> <a ng-href="/Bookings/Edit/{{otherBooking.Booking.ID}}"><span >{{otherBooking.Customer.FirstName}}</span></a> </span> </td> </tr> 

JavaScript:

 BookingService.getAllBookings().then(function(data) { $scope.bookings = data.data; }); $scope.checkOtherBookings = function(bookingTypeID, date) { var newBookingArray = []; for(var i = 0; i < $scope.bookings.length; i++) { if($scope.bookings[i].Booking.Type == bookingTypeID) { var tmpDateFrom = $scope.bookings[i].Booking.DateFrom; var tmpDateTo = $scope.bookings[i].Booking.DateTo; if(dateInRange(tmpDateFrom, tmpDateTo, date)) { newBookingArray.push($scope.bookings[i]); } } } return newBookingArray; }; 
+4
source share
1 answer

You can return the promise inside checkOtherBookings . The AngularJS parser automatically uses promises. So your code will look like this:

 $scope.checkOtherBookings = function(bookingType, date) { var deferred = $q.defer(); $scope.$watch('bookings', function(bookings) { if (!bookings) return; var newBookingArray = []; for(var i = 0; i < $scope.bookings.length; i++) { if($scope.bookings[i].Booking.Type == bookingType) { var tmpDateFrom = $scope.bookings[i].Booking.DateFrom; var tmpDateTo = $scope.bookings[i].Booking.DateTo; if(date >= tmpDateFrom && date <= tmpDateTo) { newBookingArray.push($scope.bookings[i]); } } } deferred.resolve(newBookingArray); }); return deferred.promise; }; 

I created a plunker that demonstrates the technique here: demo link .

Updated:

This approach works for AngularJS 1.0.x. The AngularJS 1.2RC parser (and possibly 1.1.x) processes the function that returns the promise in different ways, in particular, it does not return the promise, but immediately returns the internal $$v promise, which is undefined because it is not yet resolved. If you are using 1.2, I suggest getting rid of ng-init and trying one of the approaches below.

Approach No. 1:

 $scope.$watch('bookings', function(bookings) { if (!bookings) return; // filter bookings, then set $scope.otherBookings = filteredList }); 

Approach No. 2:

 $scope.getOtherBookings = function() { // return filter list here } <span ng-repeat="otherBooking in getOtherBookings()"> 

Approach No. 3:

 <span ng-repeat="otherBooking in bookings | customFilterFunction"> 
+3
source

Source: https://habr.com/ru/post/1502194/


All Articles