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



我有一个工厂:

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)

当我调用刷新时,控件不会更新那里的数据。原因何在?

PeriodDataService.refresh(user)

谢谢!

问题是,当您调用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更深一级。

您将有一个指向periodData对象而不是orders数组的 $scope 属性:

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>

这里有一个小提琴展示了这两种方法。

我在工厂中使用了$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
    })
}])

最新更新