更新工厂数据时刷新控制器

时间:2014-11-12 10:47:07

标签: angularjs

我有一家工厂:

function PeriodDataService (APIService) {

    var periodData = {}

    periodData.refresh = function(user) {
        APIService.query({ route:'period', id: user._id }, function(data) {
            periodData.orders = data[0].orders
        })
    }
    periodData.orders = []
    periodData.preiod = 1

    return periodData


}
angular
    .module('app')
    .factory('PeriodDataService', PeriodDataService)

还有一些控制器......比如这个,它使用工厂数据

function ProductionCtrl ($scope, PeriodDataService) {

    $scope.board = PeriodDataService.board
    $scope.period = PeriodDataService.period
}
angular
    .module('loop')
    .controller('ProductionCtrl', ProductionCtrl)

当我调用刷新时,Controlles不会更新数据。是什么原因?

PeriodDataService.refresh(user)

谢谢!

2 个答案:

答案 0 :(得分:1)

问题是,当您拨打refresh并且您的服务确实

periodData.orders = data[0].orders

您的服务正在将periodData.orders属性更改为指向与初始化时指定的数组不同的数组(通过periodData.orders = [])。

这会破坏您的控制器与服务中的数据阵列之间的连接,因为您的控制器设置为在您执行时指向原始阵列

$scope.orders = PeriodDataService.orders

(我实际上并未在您的示例代码中看到,但我认为您正在某处做某事)。

这简单地设置$scope.orders等于与periodData.orders相同的指针,从而指向内存中的原始数组,并允许控制器查看对该数组的更改。

当您的服务将periodData.orders更改为其他指针时,没有任何内容会更改$scope.orders的指针值,因此它仍然指向未更改的原始数组。

您可以通过不同的方式解决此问题。

方法1

您可以将服务.push()新数据放入periodData.orders,而不是将periodData.orders设置为等于返回的数据数组。所以你的refresh方法看起来像这样:

periodData.refresh = function(user) {
    APIService.query({ route:'period', id: user._id }, function(data) {
        periodData.orders.length = 0; // empty current orders array

        // push the returned orders data into orders array
        data[0].orders.forEach(function (item, index) {
            periodData.orders.push(item);
        });
    });
};

只要你只是添加或删除原始数组,并且不重新定义它(不要做另一个periodData.orders =),它应该可以正常工作。

方法2

或者,您可以创建一个新对象来保存orders数组(以及您要公开的任何其他数据元素)并使用$scope属性指向该对象而不是数组本身

所以你的服务看起来像这样:

function PeriodDataService (APIService) {
    var periodDataSvc = {};

    // create data object to hold service data
    periodDataSvc.periodData = {
        orders: [],
        period: 1
    };

    periodDataSvc.refresh = function(user) {
        APIService.query({ route:'period', id: user._id }, function(data) {
            periodDataSvc.periodData.orders = data[0].orders
        })
    }

    return periodDataSvc;
}

orders数组现在在periodDataSvc.periodData.orders更深一层。

你会有一个$scope属性指向periodData对象而不是orders数组:

function ProductionCtrl($scope, PeriodDataService) {
    $scope.periodData = PeriodDataService.periodData;
}

因此,在您的服务中,当您将orders数组设置为等于APIService中返回的数组时,控制器将看到该更改,因为它正在观察periodData对象,并且该对象的属性已更改。

当然,由于您更改了$scope属性,因此任何引用orders数组的标记都需要更改为引用periodData.orders。例如:

<div ng-repeat="order in periodData.orders">{{order.id}}: {{order.item}}</div>

这里有一个显示两种方法的fiddle

答案 1 :(得分:0)

我在工厂使用 $ rootScope ,在控制器中使用 $ scope。$ on 来解决此问题。 当我更改工厂时,我使用 $ rootScope。$ broadcast 告诉控制器我更改了它。

.factory('dataFactory', ['$http', '$rootScope', function ($http, $rootScope) {
    var dataFactory = {
        stock: null,
        getStock: getStock
    }

    function getStock() {
        $http.get("/api/itemfarmacia/").then(function success(res) {
            dataFactory.stock = res.data;
            $rootScope.$broadcast('dataFactory.stock');
        }, function error(err) {
            onsole.log("Bad request");
        })
    }

    return dataFactory;
}])

并在控制器中

.controller('atencion', ["$scope", "$state", "dataFactory", function ($scope, $state, dataFactory) {
    $scope.stock = dataFactory.stock;
    dataFactory.getStock(); //wherever you execute this, $scope.stock will change

    $scope.$on('dataFactory.stock', function () {
        $scope.stock = dataFactory.stock; //Updating $scope
    })
}])