AngularJS的ng-repeat在模型更改时不会更新

6
我在项目中有这段代码。我尝试使用$http从数据库添加数据,但是ng-repeat没有更新表格,只显示了一个空行。
当我检查scope时,数据已经存在。我阅读了许多答案,但它们似乎与我的问题无关。
<div ng-controller="TweetsController">  
<table class="table table-striped table-bordered table-hover" width="100%">
    <thead>
        <tr>
            <th class="col-md-5"><i class="fa fa-fw fa-twitter text-muted hidden-md hidden-sm hidden-xs"></i> Texto</th>
            <th class="col-md-1 text-center"> Lista</th>
            <th class="col-md-1 text-center"> Cuenta</th>
            <th class="col-md-1 text-center"> Red</th>
        </tr>
    </thead>
    <tbody>
        <tr ng-repeat="tuit in filtrado">
            <td>{{tuit.texto}}</td>
            <td class="text-center">{{tuit.lista.nombre}}</td>
            <td class="text-center">{{tuit.lista.cuenta.nombre}}</td>
            <td class="text-center">{{tuit.lista.cuenta.red.tipo}}</td>
        </tr>
    </tbody>            
</table>
<div>
    <pagination total-items="ufilter.length" itemsPerPage="itemsPerPage" ng-model="currentPage"></pagination>
</div>
</div>

控制器:

.controller('TweetsController', ['$scope','$http','filterFilter', function($scope,$http,filterFilter) {
    $scope.currentPage = 1;
    $scope.itemsPerPage = 10;
    $scope.filtrado = [];

    $scope.setPage = function (pageNo) {
        $scope.currentPage = pageNo;
    };

    // retrieve tweets
    $http.get('admin/twitter').success(function(tweets) {
        $scope.tweets = tweets;
    });

    $scope.saveTweet = function(isValid) {
        if(isValid) {
             var tuit = {
                texto: $scope.texto,
                lista_id: $scope.lista
            };

            $http.post('admin/twitter', tuit).success(function(t) {
                $scope.tweets.push(t);
            });
        }
    };

    $scope.filtrar = function(filtro) {
        if($scope.tweets != undefined) {
            $scope.ufilter = filterFilter(filtro, $scope.buscar);

            var inicio = ($scope.currentPage - 1) * $scope.itemsPerPage;
            var fin = inicio + $scope.itemsPerPage;

            $scope.filtrado = $scope.ufilter.slice(inicio, fin);
        }
    };

    $scope.$watch('tweets', function() {
        $scope.filtrar($scope.tweets);
    });

    $scope.$watch('currentPage', function() {
        $scope.filtrar($scope.tweets);
    });

    $scope.$watch('buscar', function() {
        $scope.filtrar($scope.tweets);
        $scope.setPage(1);
    });     

}])

编辑:

我解决了!

问题是检索数据的方式被包装了。

$scope.tweets.push(t[0])

请不要忘记创建一个答案并打上标签,这样人们就不会浪费时间回答一个开放性问题了。 :) - Brian Webb
4个回答

10
您需要将其应用到范围中。
 $http.get('admin/twitter').success(function(tweets) {
        $scope.tweets = tweets;
        $scope.$apply()
});

这是一篇很棒的博客文章,解释了这个问题:

http://jimhoskins.com/2012/12/17/angularjs-and-apply.html

导致你的 ng-repeat 在 $http 请求后没有更新的原因是 $http 是异步的,而且在响应返回之前,控制器的 JavaScript 已经完成了转换。所以你必须通知作用域已经发生了变化,并将其推送到作用域中。


谢谢你的回答。当我使用这个代码时,浏览器会报错:$digest already in progress :( - Charger513
我认为问题在于scope.watch,应该使用scope.watchCollection,因为集合发生变化,而不是tweets引用。您不必调用scope.$apply。 - MiTa
我尝试使用scope.watchCollection,但它做的事情是一样的。 - Charger513
非常感谢你,你救了我。 - Minkyu Kim
真正的英雄。节省了无数个小时的挫败感。谢谢你,伙计。 - Anjana Silva

3
问题在于检索数据的方式存在问题,它被包装起来了。
与其这样:
$http.post('admin/twitter', tuit).success(function(t) {
            $scope.tweets.push(t);
        });

this:

$http.post('admin/twitter', tuit).success(function(t) {
            $scope.tweets.push(t[0]);
        });

0

有简单的方法和正确的方法。

这是简单的方法

//Utility Functions
function Digest($scope) {
    //this may not be future proof, if it isn't then you may have to try $timeout(function(){//do something})
    if (!$scope.$$phase) {
        try {
            //using digest over apply, because apply fires at root, and I generally don't need root.
            $scope.$digest();
        }
        catch (e) { }
    }
    //console.log('$scope snapshot:', $scope);
}

在你的代码中,通过调用这个来使用:
        $http.post('admin/twitter', tuit).success(function(t) {
           Digest($scope.tweets.push(t));
        });

这是正确的方式。

https://docs.angularjs.org/api/ng/service/$q

将你的 HTTP 调用包装在 $q promise 中。然后,当它成功或失败时,履行承诺。Repeater 将遵守该承诺。

0

对于其他可能遇到UI不更新的问题的人 - 即使在执行$apply或在$timeout中保持,也是如此。我刚意识到我犯了一个愚蠢的错误,并且已经添加了::到嵌入属性中并忘记了它。

所以我有我的ng-repeat和里面我有一个{{ ::item.name }}。对于那些不知道::做什么的人; 它告诉angular设置数据而不设置任何其他观察者,这反过来阻止angular尝试更新该属性。这对于您知道永远不会更改的数据非常有用。请参阅下面的链接以获取有关一次性绑定的更多信息: http://blog.thoughtram.io/angularjs/2014/10/14/exploring-angular-1.3-one-time-bindings.html

所以我的解决方案就是删除::,因此:{{ ::item.name }}变成了{{ item.name }}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接