服务中的AngularJS数据触发计算功能

时间:2014-05-06 21:27:07

标签: angularjs angularjs-service

我有一个多步向导,它绑定服务中的数据(wizardStateSvc)。我希望屏幕上有一个totals元素,只要更新了影响总计的向导基值,就会更新。计算有点复杂(比我的示例中显示的更多)所以我想让它在控制器中执行。我认为$ watch会对此有用,但是发生的事情是$ watch函数在初始化期间被调用一次,并且在我更新项目时从不触发。如何让这个$ watch正确触发?

总计控制器:

myApp.controller('wizardTotalsCtrl', ['wizardStateSvc', '$scope', function (wizardStateSvc, $scope) {
    $scope.products= wizardStateSvc.quote.products;

    $scope.$watch(function() { return wizardStateSvc.quote.products; }, function(products) {
        var total= 0;

        products.forEach(function(product) {
            total += product.price * (1 - (product.dealerDiscount * 0.01)) * product.quantity;
        });

        $scope.baseTotal = total;
    });
}])

国家服务:

myApp.service("wizardStateSvc", [function () {
    var quote = {
        products: [],
        options: {},
        customer: {},
        shipping: {},
        other: {}
    }

    return {
        quote: quote
    }
}]);

2 个答案:

答案 0 :(得分:2)

如果唯一可以改变的是products数组的内容,即可以从数组中插入或删除产品但是price NOT 更改,然后使用$scope.$watchCollection。代码与您的代码相同,只需将$watch替换为$watchCollection

理由:$watch检查是否平等;由于products数组本身不会改变(即products at time t1 === products at time t2),因此永远不会触发监视。另一方面,$watchCollection监视数组的内容,因此在这种情况下它就是你想要的。

如果产品的价格也可能发生变化,则需要更高的成本$scope.$watch(...,...,true)。第3个参数的true表示深度监视,即遍历对象层次结构并检查每个嵌套属性。查看docs

答案 1 :(得分:0)

您的手表可以观看阵列产品'。当它被初始化时,products是对数组的引用,当你添加值时,产品仍然是对同一个数组的引用,它只是不同的数组内容,所以确实存在没有理由让你的手表再次调用该功能。这个问题有两个解决方案:

不太好的解决方案:观察产品的长度,这样只要产品长度发生变化,手表就会被调用。

$scope.$watch(function() { return wizardStateSvc.quote.products.length; }, ...);

在添加一个项目并在之后立即删除另一个项目的用例中存在问题。如果在此操作之前,手表的值为x,则在您执行操作后它将为x,因此无法调用。

更好的解决方案:使用手表集合,它也可以处理长度不看的用例。

$scope.$watchCollection('products', ...);

从文档(滚动到$ watchCollection部分):

https://docs.angularjs.org/api/ng/type/ $ rootScope.Scope