模型更改后ngRepeat不更新

Posted

技术标签:

【中文标题】模型更改后ngRepeat不更新【英文标题】:ngRepeat not updating after model changed 【发布时间】:2015-08-11 02:12:30 【问题描述】:

我正在尝试编写一些搜索输入代码,以使用 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();
);

搜索栏.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.$apply 但结果是一样的。

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

感谢您的宝贵时间。

【问题讨论】:

您在调试中看到的 $scope.eventi 是您的 searchCtrl 中的那个,而不是您的 mainCtrl 中的那个。要更新您的 mainCtrl $scope.eventi,您必须找到其他方法。 (一个干净但冗长的解决方案是使用服务来共享控制器中的变量,一个奇怪但简短的解决方案是使用 $broadcast 和 $on)。如果您想了解如何在控制器之间共享服务数据的清晰示例,请随时询问。但是在 plunker 中构建它需要一些时间。 谢谢,我试过了,我可以看到我用服务定义的共享属性,我现在打破 mainCtrl 来仔细检查那个控制器的 $scope,我可以看到它更新了,但视图仍然显示旧数据:( 【参考方案1】:

只是改变:

$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>

【讨论】:

谢谢,我已经尝试实施您的解决方案,即使使用 Okazari 提出的服务,当我调试代码时模型似乎更新了,但视图仍然显示旧数据:( 啊,我现在看到你的问题了。您没有使用搜索控制器将 ng-repeat 放在正确的 div 中。将更新我的答案。 感谢您的编辑,我会尝试将所有代码放在一个控制器中,但是没有任何解决方案可以让控制器更新另一个模型然后触发视图更新吗? 将所有代码放在一个控制器中解决了这个问题,但我真的不希望所有应用程序都放在一个控制器中:( 是的,我绝对同意。 @Okazari 是正确的,它需要一些时间来构建一个示例,但是有很多解决方案和教程可以在控制器之间共享数据:这是一个很好的视频youtube.com/watch?v=1OALSkJGsRw,这是一个 SO 答案***.com/questions/9293423/…【参考方案2】:

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

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

在 cmets 中回答问题:

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

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

问题

如果你像这样绑定你的变量:

服务

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

这将创建一个带有引用的“1”变量。

控制器

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

这会将 $scope.myvar 绑定到“1”引用。

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

   service.serviceVar = 2;

您将创建一个带有新引用的新变量“2”,并将此引用分配给 service.serviceVar。糟糕的是,您对旧 1 var 的所有旧引用都不会更新。

解决方案

为避免这种情况,请这样做:

服务

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

您创建一个具有新引用的对象并将其分配给 servicevar。 您创建一个 var "1" 并将其分配给 servicevar.value。

控制器

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

您将 servicevar 引用分配给您的范围变量。

查看

myvar.value

您可以通过使用 var 的属性来使用该值。

更新 var 这样做:

service.servicevar.value = 2;

您将创建一个带有新引用的新变量“2”,并用这个替换旧引用。

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

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

编辑:

尽量不要使用 $scope.$apply。这是一个非常糟糕的做法。如果你用它来做某事,你可能应该找另一个来做(我猜这对 Stacks 来说是一个很好的问题:“为什么我需要 $apply 来解决我的问题 XXXXX”)

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

这是我的一个old plunker 使用服务来共享属性

【讨论】:

非常感谢,这就是重点,与服务共享对象解决了问题。

以上是关于模型更改后ngRepeat不更新的主要内容,如果未能解决你的问题,请参考以下文章

ngRepeat 暂时显示重复列表

无法在嵌套的 ngRepeat 上触发动画

AngularJS:根据ngModel未使用ngRepeat选择单选按钮

异常记录[ngRepeat:iexp] -anggular

来自 ngRepeat 的变量在 ngClick 中不起作用

AngularJS、ngRepeat 和默认选中单选按钮