4

我在使用 AngularJS 和一个在填充数据数组之前调用的函数时遇到问题。当我的函数被调用时ng-init$scope.bookings数组还没有被评估(填充数据),导致没有数据。

我的目标是:获取特定 bookingType 和特定日期的所有预订,并将所有预订显示在<td>

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


这是我的 HTML 代码:

描述:我遍历 allbookingTypes然后遍历 all dates。执行的ng-init次数与日期一样多,并且有效。otherBookings应该是该 bookingType 和该日期的预订数组。但是,$scope.bookings尚未填充数据,因此otherBookings永远不会执行循环。

<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 代码:

描述:在顶部,BookingsController我调用了一个$scope.bookings用数据填充数组的服务,$scope.checkOtherBookings()函数如下:

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;
};

$scope.checkOtherBookings()函数被调用22 次(与日期一样多次),但console.log($scope.bookings)输出22 次 []- 所以我的观察是$scope.bookings每次调用函数时数组都是空的。

我需要某种方法来等待执行,ng-init直到$scope.bookings数组充满数据。

有任何想法吗?


更新 1 - 14.09.13

现在newBookingArray有一些数据,但otherBookings从来ng-init没有得到它们。

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;
};

更新 2 - 14.09.13

这解决了!我把作业从ng-init转移到了ng-repeat,它工作得很好。

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

1 回答 1

3

你可以在里面返回一个承诺checkOtherBookings。AngularJS 解析器自动处理 Promise。所以你的代码看起来像这样:

$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;
};

我创建了一个在这里演示该技术的 plunker:演示链接

更新:

上述方法适用于 AngularJS 1.0.x。AngularJS 1.2RC(可能还有 1.1.x)的解析器以不同的方式处理返回 promise 的函数,特别是它不返回 promise,而是立即返回 promise 的内部$$v,这是undefined因为它还没有解决。如果您使用 1.2,我建议摆脱ng-init并尝试以下方法之一。

方法#1:

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

方法#2:

$scope.getOtherBookings = function() {
   // return filter list here
}

<span ng-repeat="otherBooking in getOtherBookings()">

方法#3:

<span ng-repeat="otherBooking in bookings | customFilterFunction">
于 2013-09-14T17:54:43.197 回答