最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - AngularJS: ng-repeat doesn't refresh after updating array - Stack Overflow

programmeradmin3浏览0评论

I'm using Ionic framework, and trying to display a list of "Card" elements using the following HTML code:

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

This is my JS code used inside the controller for updating the cases array:

.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});

});
//..
})

The $scope.cases got well displayed when being initialized to a constant value, but when being dynamically updated (via $push) nothing gets displayed.

I'm using Ionic framework, and trying to display a list of "Card" elements using the following HTML code:

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

This is my JS code used inside the controller for updating the cases array:

.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});

});
//..
})

The $scope.cases got well displayed when being initialized to a constant value, but when being dynamically updated (via $push) nothing gets displayed.

Share edited Jun 20, 2016 at 17:18 user6039980 asked Jun 20, 2016 at 15:10 user6039980user6039980 3,5268 gold badges36 silver badges59 bronze badges 6
  • It looks like your code is missing some crucial details. How is the dataSnapshot variable obtained? – JLRishe Commented Jun 20, 2016 at 15:14
  • Try using a $watch and refresh on change. – James Oravec Commented Jun 20, 2016 at 15:17
  • @JLRishe I updated the code. please help. – user6039980 Commented Jun 20, 2016 at 15:18
  • @VenomFangs could you please give me an example? – user6039980 Commented Jun 20, 2016 at 15:19
  • Where are you pushing the new object array? I made a simple example with a timeout. jsfiddle/Lvc0u55v/5652 – Stubbies Commented Jun 20, 2016 at 15:27
 |  Show 1 more ment

3 Answers 3

Reset to default 2

The problem is that you're updating your model outside of the angular context. The data has changed, but angular hasn't run it's own internal digest and hasn't been made aware that any changes have occurred within your model.

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

You need to use angular's $scope.$apply method.

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

$apply([exp]); $apply() is used to execute an expression in angular from outside of the angular framework. (For example from browser DOM events, setTimeout, XHR or third party libraries). Because we are calling into the angular framework we need to perform proper scope life cycle of exception handling, executing watches.

Here's how to use $scope.$apply to get into a valid angular context and then update the data:

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});
                });
});

You could theoretically call $scope.$digest manually, but this isnt' remended according to the angular docs. $apply forwards exceptions correctly and also allows watchers to be processed. It's generally better to use this method than handling $digest on your own.

$digest(); Processes all of the watchers of the current scope and its children. Because a watcher's listener can change the model, the $digest() keeps calling the watchers until no more listeners are firing. This means that it is possible to get into an infinite loop. This function will throw 'Maximum iteration limit exceeded.' if the number of iterations exceeds 10.

Usually, you don't call $digest() directly in controllers or in directives. Instead, you should call $apply() (typically from within a directive), which will force a $digest().

You need to wrap your push call in $apply method. Because you're adding in to your array item from the outside of angular scope (from the firebase callback).

Try the following:

...
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});

                 });
             });
...

Same answer that MaKCbIMKo.

I would add that there is this easier-to-read alternative :

$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();
发布评论

评论列表(0)

  1. 暂无评论