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

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



这是我的 HTML 代码:

描述:我遍历所有 bookingTypes ,然后遍历所有 datesng-init 执行的次数与日期一样多,并且有效。 otherBookings 应该是该预订类型和该日期的预订数组。但是,$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;
};

最佳答案

您可以在 checkOtherBookings 中返回一个 promise。 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 来演示该技术: demo link

更新:

上述方法适用于 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">

关于javascript - 在填充 $scope 数组之前调用的函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18804455/

10-12 01:25
查看更多