搜索后角度ng重复视图不会更新

时间:2014-06-29 18:49:19

标签: javascript angularjs promise

我正在尝试使用服务调用来更新结果数组,然后在ng-repeat中使用它。在表单提交上,我调用必要的服务,并通过promise对象上的.then()连接我的回调。不幸的是,一旦我开始从文本输入中删除字符,视图才会更新。然后显示正确的结果。

以下是我的观点:

<div id="main" ng-controller="SearchController as searchCtrl">
        <div class="header" >
            <h1>Search and Add Tracks</h1>
        </div>
        <!--Search Bar-->
        <form class="pure-form pure-g" novalidate ng-submit="searchCtrl.search()">
            <div class="pure-u-1">
                <input class="pure-input-1" type="search" placeholder="Search for tracks" ng-model="searchCtrl.query">
            </div> 
        </form>
        <!--Search Results Table-->
        <div class="pure-u-1" >
            {{searchCtrl.results.length}}
            <div ng-repeat="track in searchCtrl.results" ng-include src="'templates/single-track-view.html'" >
            </div>
        </div>
    </div>

我的控制器代码:

app.controller('SearchController',function(){
    var searchCtrl = this;
    searchCtrl.results = [];
    searchCtrl.query = '';

    this.search = function(query){
        console.log(searchCtrl.query);
        var processTracks = function(results){
            console.log(results);
            searchCtrl.results = results[0].tracks;
            searchCtrl.results.push(results[1].tracks);
            searchCtrl.query = '';
            return results;
        }
        //search takes a DICTIONARY not a pure string
        mopidy.library.search({"any": searchCtrl.query}).then(processTracks,console.error.bind(console));
    }

});

使用AngularJS检查器时,我绝对可以看到searchCtrl.results在范围内更新并获得正确的结果。在我开始删除字符之前,视图根本不会更新。

编辑:来自promise的结果实际上是一系列响应。我从Mopidy(一个音乐播放器)打电话给api,阵列是来自不同音乐提供商的不同回应。

3 个答案:

答案 0 :(得分:1)

调用$scope.$apply存在风险,但摘要循环确实存在问题。

正确的方法是通过调用$q.when来调用Angular中的调用:

app.controller('SearchController',function($q){ // note the $q here for promises
    var searchCtrl = this;
    searchCtrl.results = [];
    searchCtrl.query = '';

    this.search = function(query){
        console.log(searchCtrl.query);
        var processTracks = function(results){
            console.log(results);
            searchCtrl.results = results[0].tracks;
            searchCtrl.results.push(results[1].tracks);
            searchCtrl.query = '';
            return results;
        }
        //$q.when assimilates a third party promise into Angular
        $q.when(mopidy.library.search({"any": searchCtrl.query}))
        .then(processTracks,console.error.bind(console));
    }

});

但为什么会这样呢?什么是$ q?

如果我们仔细查看代码,我们会注意到.then

那个.then是一个承诺 - 对并发的抽象是如何表明API调用的价值现已准备就绪。

Promise库,至少是体面的库运行在一个名为"Promises/A+"的规范上,告诉他们如何与彼此交互 - 所以Angular的promise库 - $q - 可以无缝地使用mopidy.library承诺

Angular的$ q承诺是hooked directly into the digest loop,因此将第三方承诺投射到Angular中会使其与摘要循环同步,而不是自己强制进行第二次摘要。

答案 1 :(得分:0)

除非你的track属性是一个数组,否则没有意义

      searchCtrl.results = results[0].tracks;
      searchCtrl.results.push(results[1].tracks);

如果它是一个数组,你通过重新定义它来打破ng-repeat和观察变量之间的联系。如果mopidy是一个外部库,你需要在更新结果变量后对你的更改进行$ pply

答案 2 :(得分:0)

正如其他人所指出的,这里的解决方案是打电话给$scope.$apply();

原因: 当你制作XHR时,它超出了角度的常规摘要周期,即当它更新所有用于双向数据绑定的侦听器时。调用$ apply,强制摘要以便更新所有收听模型。

Per angular docs on $apply