ngRepeat不更新阵列

时间:2016-08-06 14:48:10

标签: javascript angularjs

问题

我有一个ngMake()功能向makepost.php发出请求,并使用用户的输入添加了一个新的"帖子"到数据库。这个操作是成功的,我知道这一点,因为在我填写makepost.html表单并刷新页面后,新创建的帖子就在那里。我想要它,以便页面不需要刷新。因为我已经收集了Angular的双向数据绑定应该自动处理,所以也许我对$scope有一些问题,我一直在读,但我想因为我是一个初学者,我真的不知道导致这个问题的原因,或者我是否应该创建一个使用$scope.$watch()的新功能,我尝试了$scope.$apply()。我不知道,任何事情都会有所帮助,谢谢。

工厂' postFactory'

app.factory('postFactory', function($http) {
var postFactory = {
    async: function() {
        var promise = $http.get('server/blog/posts.php')
            .success(function(response) {
                return response;
            })
            .error(function(error, status) {
                $scope.response.error = { message: error, status: status };
                console.log($scope.response.error.status);
            });
        return promise;
    }
};
return postFactory;

});

在blog.controller

postFactory.async().then(function(response) {
    $scope.posts = response.data.Posts;
});

HTML

<div ng-controller="BlogController as blog">
<div class="dont-break-out" ng-repeat="post in posts">
    <a href="#{{post.Slug}}">
        <hr>
        <h4>{{post.Title}}</h4>
        <div ng-bind-html="ngHTML((post.Content | limitTo : 125) + '..')"></div>
    </a>
    <footer class="text-right"> On {{post.DateSubmited}}
        <br> By {{post.UserName}}
    </footer>
</div>
<hr>

GitHub

上的整个项目

2 个答案:

答案 0 :(得分:0)

你确定要在数据属性中返回帖子列表吗?我在posts.php中读取你的代码,我确实找到了一个包含帖子列表的对象,但它就像那样返回

echo json_encode(array(
        'Posts' => $rows
     ));

并在你要求的js代码中

$scope.posts = response.data.Posts;

也许是你对当时正在处理的承诺类型感到困惑,当你使用$ http方法它确实返回一个数据属性时,但正常的承诺不会这样做,你可以访问直接对象中的数据如下:

$scope.posts = response.Posts;

答案 1 :(得分:0)

你的ng-repeat没有更新,因为它总是指向原始的posts数组,即使你有一个新数组。

在您的初始页面加载时,您会从服务器获得一个全新的数组(让我们称之为array1),并将该数组提供给$scope你的ng-repeat 。当您发布新帖并再次拨打async()时,您会返回另一个全新数组(array2),然后将其提交给$scope ,但 ng-repeat。它已经有了它的阵列;很开心它不知道或不关心$scope认为新阵列是什么 - 它们可以指向完全不同的列表。

这是一个微妙的问题,你可以看到很多Angular视图,这是你经常会看到人们建议你永远不会在视图中引用任何东西而不将其作为其他东西的属性访问的原因之一。这样,当您更改容器对象上的属性时,ng-repeat将看到更改,因为它正在观察容器对象的属性,而不是仅仅持有自己的引用而没有与其他任何内容的连接。

要解决您的问题,您可以创建一个新的容器对象(让我们称之为data),然后在其上放置posts属性。

因此,在您的blogController中,您将首先声明

$scope.data = {};

然后您对async()的调用看起来像

postFactory.async().then(function(response) {
    $scope.data.posts = response.data.Posts;
});

并且您的ng-repeat看起来像

ng-repeat="post in data.posts"

最终结果是ng-repeat将保留data的引用并且永远不会让它继续,并且每次posts属性更改时它都会自动注意和更新。

另外,您不需要在任何回调处理程序中调用$ scope.apply()。 Angular在每个$ http请求完成时调用$ scope.apply()。