【问题标题】:AngularJS: ng-repeat doesn't refresh after updating arrayAngularJS:更新数组后 ng-repeat 不刷新
【发布时间】:2016-06-21 01:18:20
【问题描述】:

我正在使用 Ionic 框架,并尝试使用以下 HTML 代码显示“卡片”元素列表:

<div ng-repeat="case in cases">

    <div class="list card">

      <div class="item item-avatar">
        <button ng-click="rmpost(card.key)" style="background: transparent; border: none;"><i class="icon ion-close-round"></i></button><!--if (dataSnapshot.val().volunteer_email == firebase.auth().currentUser.email)-->
        <h2>{{card.volunteer_name}} ({{card.volunteer_email}})</h2>
        <p>{{card.title}} ({{card.creationdate}})</p>
      </div>

      <div class="item item-body">
        <img class="full-image" src={{card.snapshot}}>
        <p>{{card.message}}</p>
      </div>

    </div>

      </div>

这是我在控制器内部用于更新案例数组的 JS 代码:

.controller('campaignslookCtrl', function($rootScope, $scope, $cordovaGeolocation, $state, $ionicPopup, Util)
        {
            $scope.reload = function()
            {
            $scope.reload();
            }

            $scope.rmpost = function(key)
            {
              alert("rmpost");
            }

            $scope.cases = [];

            //...

    firebase.database().ref('/cases')
        .on('child_added', function(dataSnapshot)
            {

            $scope.cases.push({key: dataSnapshot.key,
                                     volunteer_name: dataSnapshot.val().volunteer_name,
                                     volunteer_email: dataSnapshot.val().volunteer_email,
                                     title: dataSnapshot.val().title,
                                     creationdate: '',//(new Date(dataSnapshot.val().creationdate)).toString(),
                                     snapshot: dataSnapshot.val().snapshot,
                                     message: dataSnapshot.val().message});

});
//..
})

$scope.cases 在初始化为常量值时显示良好,但在动态更新(通过 $push)时没有任何显示。

【问题讨论】:

  • 您的代码似乎缺少一些关键细节。 dataSnapshot这个变量是怎么得到的?
  • 尝试使用$watch 并在更改时刷新。
  • @JLRishe 我更新了代码。请帮忙。
  • @VenomFangs 你能给我举个例子吗?
  • 你在哪里推新的对象数组?我用超时做了一个简单的例子。 jsfiddle.net/Lvc0u55v/5652

标签: javascript angularjs ionic-framework angularjs-ng-repeat


【解决方案1】:

您需要将您的push 调用包装在$apply 方法中。因为您是从角度范围之外(来自 firebase 回调)添加到您的数组项中。

尝试以下方法:

...
firebase.database().ref('/cases')
        .on('child_added', function(dataSnapshot)
            {
                $scope.$apply(function () {
                    $scope.cases.push({key: dataSnapshot.key,
                                     volunteer_name: dataSnapshot.val().volunteer_name,
                                     volunteer_email: dataSnapshot.val().volunteer_email,
                                     title: dataSnapshot.val().title,
                                     creationdate: '',//(new Date(dataSnapshot.val().creationdate)).toString(),
                                     snapshot: dataSnapshot.val().snapshot,
                                     message: dataSnapshot.val().message});

                 });
             });
...

【讨论】:

    【解决方案2】:

    问题是您在角度 context 之外更新模型。数据已更改,但 Angular 尚未运行它自己的内部摘要,并且尚未意识到您的模型中发生了任何更改。

    firebase.database().ref('/cases')
            .on('child_added', function(dataSnapshot) //FIREBASE EVENT NOT WITHIN ANGULAR CONTEXT
    

    你需要使用angular的$scope.$apply方法。

    https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$apply

    $apply([exp]); $apply() 用于执行 Angular 中的表达式 从角度框架之外。 (例如来自浏览器 DOM 事件、setTimeout、XHR 或第三方库)。 因为我们是 调用我们需要执行适当范围的角度框架 异常处理、执行手表的生命周期。

    以下是如何使用$scope.$apply 进入有效的角度上下文,然后更新数据:

    firebase.database().ref('/cases')
            .on('child_added', function(dataSnapshot)
                {
                    $scope.$apply(function() {
                        //we are now within the angular context, so any updates to the model with be handled correctly
                        $scope.cases.push({key: dataSnapshot.key,
                                         volunteer_name: dataSnapshot.val().volunteer_name,
                                         volunteer_email: dataSnapshot.val().volunteer_email,
                                         title: dataSnapshot.val().title,
                                         creationdate: '',//(new Date(dataSnapshot.val().creationdate)).toString(),
                                         snapshot: dataSnapshot.val().snapshot,
                                         message: dataSnapshot.val().message});
                    });
    });
    

    理论上,您可以手动调用$scope.$digest,但根据 angular 文档,不建议这样做。 $apply 正确转发异常并允许处理观察者。通常使用这种方法比自己处理$digest 更好。

    $digest();处理当前作用域的所有观察者及其 孩子们。因为观察者的听众可以改变模型,所以 $digest() 不断调用观察者,直到没有更多的听众 射击。这意味着有可能进入无限循环。 此函数将抛出“超出最大迭代限制”。如果 迭代次数超过10次。

    通常,您不会直接在控制器或中调用 $digest() 指令。相反,您应该调用 $apply() (通常在 directive),它将强制执行 $digest()。

    【讨论】:

    • 在尝试之后:我显示的是空白数据,而不是 dataSnapshot.val().*.*.中的数据。
    • @user6039980 应该可以工作 - 您的控制台中有任何错误吗?
    • 抱歉,您的回答很完美。我忘记了将 {{card.*}} 重命名为 {{case.*}},这就是导致问题的原因。非常感谢,这有帮助。
    • 我只是想补充一点,按钮 ng-click 不起作用。
    • @user6039980 很高兴为您提供帮助!不幸的是,您的问题中没有足够的信息来解决 ng-click 问题。我建议您针对此问题打开一个附加问题,并提供更多详细信息。
    【解决方案3】:

    与 MaKCbIMKo 的答案相同。

    我要补充的是,有一个更易于阅读的替代方案:

    $scope.cases.push({key: dataSnapshot.key,
                                     volunteer_name: dataSnapshot.val().volunteer_name,
                                     volunteer_email: dataSnapshot.val().volunteer_email,
                                     title: dataSnapshot.val().title,
                                     creationdate: '',//(new Date(dataSnapshot.val().creationdate)).toString(),
                                     snapshot: dataSnapshot.val().snapshot,
                                     message: dataSnapshot.val().message});
    
    $scope.digest();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-02
      • 2016-02-12
      • 1970-01-01
      • 1970-01-01
      • 2014-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多