$ scope有选择地更新服务解析

时间:2014-10-11 14:31:52

标签: javascript angularjs

问题

我有一个异步提取数据并将其提供给控制器的服务。在那里,它被附加到$scope并在视图中使用 我不明白的是更新方面的差异,具体取决于控制器中此服务的使用方式。

实施例

该服务不提供数据承诺,而是公开数据本身。我已经通过超时模拟了它:

(编辑:我已将初始化添加到Opt变量,以表明这不能解决问题。)

app.service("Options", ["$q", "$timeout", function ($q, $timeout) {
    var Opt = {
        people:[],
        symbols:[],
        countries:[]
    };

    $timeout(function () {
        Opt.people = [ {frst: "Johnny", last: "Walker"},
                       {frst: "Jack", last: "Daniels"},
                       {frst: "Jim", last: "Bean"} ];
    }, 1000);

    $timeout(function () {
        Opt.symbols = [ {name: "Pi", descr: "circles"},
                        {name: "Phi", descr: "ratios"},
                        {name: "Psi", descr: "waves"},
                        {name: "Chi", descr: "distributions"} ];
    }, 2000);

    $timeout(function () {
        Opt.cities = [ {name: "Amsterdam", country: "Netherlands"},
                       {name: "Cairo", country: "Egypt"},
                       {name: "Santiago", country: "Chile"} ];
    }, 3000);

    /* etc */

    return Opt;
}]);

然后在控制器中使用它,如下所示:

app.controller("Ctrller", ["$scope", "Options", "$timeout", function ($scope, Options, $timeout) {
    $scope.options = Options; //updating
    $scope.symbols = $scope.options.symbols; //not updating
    $scope.symbols = Options.symbols; //not updating either

    $timeout(function(){
        $scope.symbols = $scope.options.symbols; //updating
    }, 4000);

}]);

我在Plnkr here中创建了一个现场演示。

如您所见,视图中的第二个select元素(以及$scope的'符号'属性)在4而不是2秒后更新。如果控制器中没有$timeout,那么这当然不会发生。

为什么会这样?为什么这些变化没有通过?

谢谢!

2 个答案:

答案 0 :(得分:1)

您正试图在$scope.symbols服务返回的对象中存在$scope.options.symbols数组之前将Options.symbols分配给symbolsOptions,所以它( $scope.symbols)被赋予undefined,而不是对符号对象的引用。您可以通过在尝试分配之前添加几个控制台语句来查看此内容。由于symbols对象尚未存在,因此您的$scope.symbols变量无法引用它。

这不是peoplecities的问题,因为您通过$scope.options对象访问它们,该对象引用了由Opt对象返回的Options对象ng-repeats服务。由于基准引用保持不变,因此people会看到对citiesOptions.symbols子对象的更改。

如果您真的想将$scope.symbols分配给$scope.options.symbols,可以通过$scope.$watch('options.symbols', function(value) { $scope.symbols = value; }); 上的观看完成:

people

更新示例plunker后编辑

修订后的plunker仍然表现出相同的行为,因为cities中正在覆盖已初始化的symbols$timeout=。如果您希望保持引用相同,则不得使用$timeout中的$timeout(function () { results = [ {name: "Pi", descr: "circles"}, {name: "Phi", descr: "ratios"}, {name: "Psi", descr: "waves"}, {name: "Chi", descr: "distributions"} ]; angular.forEach(results, function(result) { Opt.symbols.push(result); }); }, 2000); 运算符。一种选择是遍历返回的列表并使用推送添加每个项目:

Opt.symbols

Here is a revised plunker with my suggested changes.

可能有更好的方法来实现这一点,但关键是你不能将Opt.symbols重新分配给其他对象(即使其他对象也是一个数组)。

另一种方法是将$scope.symbols更改为包含数组的对象,引用Opt.symbols指向对象(Opt = { people: [], symbols: {}, cities: [] } $timeout(function() { Opt.symbols.values = [ {name: "Pi", descr: "circles"}, {name: "Phi", descr: "ratios"}, {name: "Psi", descr: "waves"}, {name: "Chi", descr: "distributions"} ]; }, 2000); )并查看内部值。

ng-options="s as s.name for s in symbols.values"

如果你走了那条路,你需要调整你的ng选项,看起来像,

$timeout

Here is a working plunker of this approach.

除了我给出的两个示例之外,您还可以采取其他方法,这对您的项目必须做出决定是有意义的。关键点在于,Opt.symbols您无法重新分配$scope.symbols的值并期望{{1}}引用新值。

答案 1 :(得分:0)

在index.html中,您正确指定了'options.people'和'options.options'的ng-options,但忘了为'symbols'指定

在:

ng-options="s as s.name for s in symbols"

后:

ng-options="s as s.name for s in options.symbols"

这是新的傻瓜:

http://plnkr.co/edit/HqPQM5Qqfq7gi9KWQLKJ?p=preview