2

I'm using AngularJS in a Firebase app and I have a function where I do some inner join to get some data. More details here. After getting the response from the firebase api I create an object and push it into an array (a scope variable). I see in the debug that the data has been retrieved and that the $scope variable is filled correctly. The problem is that it is not showing in the ng-repeat.

My function:

$scope.getMessagesByRegion = function(regionId){

    console.log('Function start');
    var rootRef = firebase.database().ref();
    var regionMessagesRef = rootRef.child("region_messages/"+ regionId);
    $scope.messages_by_region = []; // Here I reset the scope variable

    regionMessagesRef.on('child_added', function(rmSnap) {

        var messageRef = rootRef.child("messages/"+rmSnap.key);
        messageRef.once('value').then(function(msgSnap){

            var msg = {
                key : msgSnap.key,
                name : msgSnap.val().name,
                type : $scope.getTypeName(msgSnap.val().type),
                show_only_once : rmSnap.val().show_only_once,
                pre_requisite_message : rmSnap.val().pre_requisite_message
            }
            console.log(msg); // here I see the object in the console. it is OK
            $scope.messages_by_region.push(msg); // pushing the item
            console.log('----------------');
            console.log($scope.messages_by_region);
        })

    });
}

My HTML:

            <table class="table">
                <thead>
                <tr>
                    <th>Message name</th>
                    <th>Type</th>
                    <th>Show only once</th>
                    <th>Pre requisite</th>
                </tr>
                </thead>
                <tbody>
                <tr ng-repeat="msg in messages_by_region">
                    <td ng-bind="msg.name"></td>
                    <td ng-bind="msg.type"></td>
                    <td ng-bind="msg.show_only_once"></td>
                    <td ng-bind="msg.pre_requisite_message"></td>
                </tr>
                </tbody>
            </table>

This is what I see in the console:

enter image description here

The problem is that even having an object in the array it is not shown in the view. It is like there was an empty array set to the $scope.messages_by_region variable

I'm having a hard time figuring out what I'm doing wrong. Can you see what's wrong with my function?

Thanks for any help.

Community
  • 1
  • 1
André Luiz
  • 6,642
  • 9
  • 55
  • 105
  • Try adding the console.log($scope.messages_by_region); to a test function and make a ng-click call this function and see what happens. Also do you see any error in the console? – Gustavo Gabriel Dec 12 '16 at 17:49
  • did you try without ng-bind directive? `{{msg.name}}` – Azad Dec 12 '16 at 17:49

3 Answers3

2

try,

$scope.$apply(function(){
 $scope.messages_by_region.push(msg);
});

or,

$scope.messages_by_region.push(msg);
$scope.$apply();
Azad
  • 5,144
  • 4
  • 28
  • 56
  • Worked! Thanks! Apply receiving a function so it checks only for the value affected inside that function? – André Luiz Dec 12 '16 at 18:02
  • you calling a non angular function `messageRef.once` therefore you have to tell the angular that some $scope variable changed . – Azad Dec 12 '16 at 18:06
1

Since you're using async functions (Cosuming of firebase API) you should tell angular to refresh the HTML;

Use

$scope.$diggest()

More information you can find on https://www.sitepoint.com/understanding-angulars-apply-digest/

Rodolfo Marcos
  • 159
  • 1
  • 6
1

As you are performing Async calls you need to tell angular to refresh the changes in the value with $apply call you can do it with:

$scope.getMessagesByRegion = function(regionId) {

  console.log('Function start');
  var rootRef = firebase.database().ref();
  var regionMessagesRef = rootRef.child("region_messages/" + regionId);
  $scope.messages_by_region = []; // Here I reset the scope variable

  regionMessagesRef.on('child_added', function(rmSnap) {

    var messageRef = rootRef.child("messages/" + rmSnap.key);
    messageRef.once('value').then(function(msgSnap) {
        var msg = {
          key: msgSnap.key,
          name: msgSnap.val().name,
          type: $scope.getTypeName(msgSnap.val().type),
          show_only_once: rmSnap.val().show_only_once,
          pre_requisite_message: rmSnap.val().pre_requisite_message
        }

      $scope.$apply(function() {
        console.log(msg); // here I see the object in the console. it is OK
        $scope.messages_by_region.push(msg); // pushing the item
        console.log('----------------');
        console.log($scope.messages_by_region);
      });
    });
  });
}

For more information on this behavior you can also read article describing the problem here

Seeker
  • 1,877
  • 4
  • 32
  • 56