AngularJS中的服务未更新View

时间:2014-02-23 08:08:32

标签: javascript angularjs

我已经阅读了几篇与此问题相关的帖子和​​文章,他们帮助我设计了一些工作但是没有解释(至少以我理解的方式)为什么这不起作用。

我创建了一个工厂服务,其工作是管理一个大陆列表和一个选定的大陆。控制器通过表示为对象文字的公共API与此服务进行交互。

var appSvcs = appSvcs || angular.module("app.services", ["app.repositories"]);
appSvcs.factory('ContinentService', ['ContinentRepository',
    function (db) {
        'use strict';

        //#region Private Fields and Variables
        var continents = [],
            selectedContinent = null;
            selectedContinentIndex = -1;
        //#endregion Private Fields and Variables

        //#region Private Methods

        function initContinents() {
            return db.getContinents(); // return a promise
        };

        function setSelectedContinent(continent) {

            selectedContinent = angular.copy(continent);
            selectedContinentIndex = continents.indexOf(continent);
        };

        //#endregion Private Methods

        //
        // Public API
        return {
            continentService: {
                continents: continents,
                selectedContinent: selectedContinent,
                setSelectedContinent: setSelectedContinent,
                initContinents: initContinents,

            }
        }

    }]);

控制器通过公共API与continentService交互。在控制器中,我在本地$ scope ...

上添加了对API的引用
$scope.svc = svc.continentService;

由于工厂应该是单件,我期望的是当控制器调用公共方法" setSelectedContinent()"时,将设置selectedContinent和selectedContinentIndex属性,然后可以使用主机控制器和实现此工厂的任何其他控制器。事实证明并非如此。在下面的第二行中,会抛出类型错误..."无法读取属性' Id' of null"。这表明未设置服务的selectedContinent属性。

$scope.svc.setSelectedContinent(continent);
console.log($scope.svc.selectedContinent.Id + " :: " + $scope.svc.selectedContinent.Name);

然而,当我直接设置属性时,它工作正常 - sorta。有一个处理,方法setSelectedContinen()t需要执行,直接设置它显然不允许这种情况发生。

$scope.svc.selectedContinent = continent;
console.log($scope.svc.selectedContinent.Id + " :: " + $scope.svc.selectedContinent.Name);

我已将完整的控制器代码包含在内,以备参考。

angular.module("ListMgrApp").controller('ContinentPanelCtrl',
    ['$scope', 'ContinentService',
        function ($scope, svc) {
            'use strict';

            //#region Fields and Variables
            $scope.svc = svc.continentService;
            var $uiContinentList = $('.continent-list');
            ///#endregion Fields and Variables

            //#region private methods
            function init() {

                //
                // Show the pane
                $scope.svc.initContinents().then(
                    function (response) {
                        $scope.svc.continents = response.data;
                    },
                    function (reason) {
                        //TODO: Handle Error
                    });
            };
            //#endregion private methods

            //#region $scope methods

            $scope.setSelectedContinent = function (continent) {

                // $scope.svc.selectedContinent = continent; <-- works but not sufficient
                $scope.svc.setSelectedContinent(continent); // <-- Needs to work but does not
                console.log(continent.Id + " :: " + continent.Name);
                $uiContinentList.find('li[data-id="' + continent.Id + '"]').addClass("selected");
            }
            //#endregion $scope methods

            init();
        }]);

1 个答案:

答案 0 :(得分:2)

引用您的setSelectedContinent

function setSelectedContinent(continent) {

            selectedContinent = angular.copy(continent);
            selectedContinentIndex = continents.indexOf(continent);
        };

您的功能设置selectedContinentselectedContinentIndex。但是这两个变量是本地变量 function (db)通过闭包可用于您的功能,而不是您服务的属性。这就是为什么你试图访问它时出错:

$scope.svc.selectedContinent.Id

在你的第二个例子中:

$scope.svc.selectedContinent = continent;

您直接设置为svc =&gt;的属性恢复它肯定不会有错误。但在这种情况下,您要在svc上创建另一个属性,该属性与声明区域中的selectedContinent 不一样

var continents = [],
            selectedContinent = null;
            selectedContinentIndex = -1;

<强>解决方案:

如果您需要将变量创建为私有(仅可通过闭包访问)。您可以提供一些getter函数来返回这些变量:

function getSelectedContinent(continent) {
            return selectedContinent;
        };

修改您返回的对象:

return {
            continentService: { 
                continents: continents, //remove this if you need a true private property
                selectedContinent: selectedContinent, //remove this if you need a true private property
                setSelectedContinent: setSelectedContinent,
                initContinents: initContinents,
                getSelectedContinent: getSelectedContinent //return 1 more function
            }
        }