模型更改后ngRepeat不更新

时间:2015-05-28 14:00:00

标签: angularjs angularjs-ng-repeat ngresource

我想编写一些搜索输入来使用ngResource从数据库中获取数据。

数据显示在带有ng-repeat的页面中,但是当我进行搜索并且$ scope已更新时,视图不会更新并显示旧数据。

以下是代码:

main.html(活动视图)

<div ng-controller="searchCtrl as searchCtrl" layout="column">
    <form class="form-inline search-form col-md-offset-1">
        <div class="form-group col-md-5">
            <label class="sr-only" for="search_location">Location</label> <input
                id="search_location" type="search" class="form-control"
                ng-Autocomplete ng-model="place" placeholder="Location" />
        </div>
        <div class="form-group col-md-5">
            <label class="sr-only" for="search_tags">Tags</label> <input
                style="width: 100%;" id="search_tags" type="search"
                class="form-control" id="search_tags" placeholder="Tags">
        </div>

        <div class="col-md-1">
            <md-button class="md-fab md-mini" aria-label="Search" ng-click="searchCtrl.search()"> <md-icon class="md-fab-center"
                md-font-icon="glyphicon glyphicon-search" style="color: black;"></md-icon>
            </md-button>
        </div>
    </form>
</div>

<div ng-controller="mainCtrl">

    <div ng-repeat="evento in eventi" ng-include="'views/components/event_card.html'" class="col-md-3"></div>

</div>

main.js

'use strict';
app.factory('Eventi', function($resource) {
    return $resource('/eventsws/events/:location', {location : '@location'}, { 
        search: {
            method: 'GET',
            params: {
                'location' : "@location"
            },
            isArray : true
        }
    })
});

app.controller('mainCtrl', function($scope, Eventi) {
    $scope.eventi = Eventi.query();
});

searchbar.js

'use strict';
app.controller('searchCtrl', function($scope, Eventi) {
    $scope.place = null;

    this.search = function() {

        $scope.eventi = Eventi.search({
            'location' : $scope.place
        });
    }
});

当它启动时从数据库中获取所有数据并正确显示它们,当我尝试进行搜索时,$ scope.eventi被更新(我可以从调试中查看$ scope.eventi中的新数据)但视图仍然显示旧数据,从不更新。

我尝试使用$ scope。$在搜索功能结束时应用但结果是相同的。

你知道它为什么不工作吗?

感谢您的时间。

2 个答案:

答案 0 :(得分:6)

您在调试中看到的$ scope.eventi是searchCtrl中的那个,而不是mainCtrl中的那个。要更新mainCtrl $ scope.eventi,你必须找到另一种方法。

干净但很长的解决方案是使用服务来共享控制器中的变量。

回答评论中的问题:

  

我可以看到它已更新,但视图仍显示旧数据

我想问题是什么(即使我实际上没有看到你的代码)。

问题

如果你像这样绑定var:

<强>服务

[...]
service.serviceVar = 1;
return service
[...]

这将创建一个&#34; 1&#34;带引用的var。

控制器

  [...]
  $scope.myvar = Service.serviceVar;
  [...]

这会将$ scope.myvar绑定到&#34; 1&#34;参考

如果您在服务中或在其他控制器中执行此操作:

   service.serviceVar = 2;

您将创建一个新的var&#34; 2&#34;使用新引用,您将此引用分配给service.serviceVar。对旧的1 var的所有旧引用都不会更新。

<强>解决方案

为避免这样做:

<强>服务

[...]
service.servicevar = {};
service.servicevar.value = 1;
return service
[...]

使用新引用创建对象并将其分配给servicevar。 你创建了一个var&#34; 1&#34;并将其分配给servicevar.value。

控制器

[...]
$scope.myvar = Service.servicevar;
[...]

将servicevar引用分配给范围var。

查看

{{myvar.value}}

您可以使用var。

的属性来使用该值

更新var执行此操作:

service.servicevar.value = 2;

您将创建一个新的var&#34; 2&#34;使用新引用并替换此引用的旧引用。

但是这次你在控制器中保存了对servicevar的所有引用。

我希望我很清楚,它会回答你的问题。

编辑:

尽量永远不要使用$ scope。$ apply。这是一个非常糟糕的做法。如果你使用它来制作一些东西,你应该找到另一个可以做到这一点(对于Stacks我将会是一个很好的问题:&#34;为什么我需要$申请来解决我的问题XXXXX&#34;)

rsnorman15对您使用异步调用有一个很好的观点。看看他的答案。

以下是我使用服务共享属性的old plunker之一

答案 1 :(得分:2)

只需改变:

$scope.eventi = Eventi.search({
   'location' : $scope.place
});

Eventi.search({
  'location' : $scope.place
}, function(eventi) {
  $scope.eventi = eventi
});

这是一个异步调用,因此必须在成功处理程序中进行分配。

您遇到的另一个问题是ng-repeat未包含在searchCtrl范围内的div中。更新您的HTML,使其包含如下:

<div ng-controller="searchCtrl as searchCtrl" layout="column">
  <form class="form-inline search-form col-md-offset-1">
    ... form stuff
  </form>

  <div ng-repeat="evento in eventi" ng-include="'views/components/event_card.html'" class="col-md-3"></div>
</div>