解决另一个资源的资源依赖性

时间:2014-01-06 23:18:49

标签: angularjs angularjs-resource

我有一个资源,其数据依赖于另一个资源。 TransactionSplitTransaction绑定,其中包含一系列交易。 在交易中,我需要知道SplitTransaction的交易总数。

这是我的资源:

.factory('Transaction', ['$resource', '$http', '$rootScope', 'SplitTransaction', '$q', function($resource, $http, $rootScope, SplitTransaction, $q){
    var Transaction = $resource('/api/v1/transaction/:id', {}, {
        query: {
            method: 'GET',
            isArray: true,
            transformResponse: tastypieDataTransformer($http).concat(function (data, headersGetter) {
                for (var idx in data) {
                    var transaction = data[idx];

                    if (transaction.installment_of) {
                        var split = transaction.installment_of.split('/');
                        var installmentId = split[split.length-1];

                        SplitTransaction.get({id: installmentId}).$promise.then(function (installment) {
                            transaction.installment_total = installment.transactions.length;
                        });
                    }
                }
                return data;
            })
        }
    });

这是html:

<tr class="transaction-row" ng-repeat="transaction in group.transactions">
    <td ng-bind="transaction.installment_total"></td>
</tr>

它在渲染的html上没有显示任何内容。

我试图使用承诺:

transformResponse: tastypieDataTransformer($http).concat(function (data, headersGetter) {
    for (var idx in data) {
        var transaction = data[idx];

        if (transaction.installment_of) {
            var split = transaction.installment_of.split('/');
            var installmentId = split[split.length-1];

            var deferred = $q.defer();

            SplitTransaction.get({id: installmentId}).$promise.then(function (installment) {
                var installment_total = installment.transactions.length;
                deferred.resolve(installment_total);
            });
            transaction.installment_total = deferred.promise;
        }
    }
    return data;
})

现在绑定似乎有效,但它只在html上显示[object Object]

我做错了什么?

修改

如果我将transaction.installment_total设置在SplitTransaction.get回调之外,它会显示在HTML上,因此绑定就可以了。就像这样:

if (transaction.installment_of) {
    var split = transaction.installment_of.split('/');
    var installmentId = split[split.length-1];

    transaction.installment_total = 0;  // shows "0" on the html


    SplitTransaction.get({id: installmentId}, function (installment) {
        ...
    });
}

由于某种原因,回调内部发生的事情并未反映出绑定......

临时解决方案:

我将代码从transformResponse移除到我加载Transaction的位置:

Transaction.query(filter).$promise.then(function (result) {                      

    $.each(result, function (idx, transaction) {                                 
        if (transaction.installment_of) {                                        
            var split = transaction.installment_of.split('/');                   
            var installmentId = split[split.length-1];                           
            transaction.installment_total = 0;                                   

            SplitTransaction.get({id: installmentId}, function (installment) {   
                transaction.installment_total = installment.transactions.length; 
            });                                                                  
        }                                                                        
    });                                                                          

    $scope.allTransactions = result;                                             
    $scope.transactionGroups = groupTransactions($scope.groupBy);                

    window.transactions = $scope.transactionGroups;                              

}).finally(function () {$scope.loading = false;});

不能说为什么会这样。也许对象在transformResponse之后被复制,使我在回调范围上对transaction的引用变得无用......

1 个答案:

答案 0 :(得分:0)

不太明显,你的html中的transaction.installment_total被绑定了什么。通常它可能是$ rootScope的属性或绑定控制器的$ scope,我在这里看不到任何控制器。

另外,不明显,什么是group.transactions。如果它是空的,则不会呈现任何内容。

但是如果你以某种方式管理将transaction.installment_total绑定到你的html,那么问题出在这里:

transaction.installment_total = deferred.promise;

您正在将Promsie对象绑定到您的html,并且您需要绑定此承诺的结果:

deferred.promise.then(function(result) {
   transaction.installment_total = result;
});

那就是你想使用promises。但还有另一种方式。

ngResource的方法返回承诺,您可以将其分配给您的视图,当数据可用时,此承诺将替换为此数据。

这是documentation

  

一旦数据到达,拥有一个空对象就不会渲染   从服务器然后该对象填充数据和   视图自动重新呈现自己显示新数据。这意味着   在大多数情况下,人们永远不必为此编写回调函数   行动方法

换句话说......

var result = SplitTransaction.get({id: installmentId}, function() {
   transaction.installment_total = result.transactions.length
});

......也应该有用。