0

I am using Angular and TingoDB (Mongo) inside Node Webkit for a single page application. However I have a strange problem that I have been unable to resolve.

When I use an object literal (option 2) the data displays correctly in the html page. However changing the code to return data from the database (option 1) the results do not appear on the html page. I have converted both styles of data into the a JSON string to prove consistency and then using the angular.fromJSON to return an object. Both methods return the same JSON string in console.log and before anyone asks I have either Option 1 or Option 2 commented out so both are not running concurrently.

I have copied the JSON string based on the data passed from TingoDB into the console.log and re-entered it into the code below to ensure that no differences between the 2 versions of the data existed without changing any other code, but the problem still persists.

Can anyone shed light on why this occurs and how to fix it?

var app = angular.module('myApp', []);
var Engine = require('tingodb')(),
    assert = require('assert');

var db = new Engine.Db('./db', {});
var collection = db.collection("clean.db");

app.controller('tingoDataCtrl', ['$scope', function($scope) {



     function getData(callback) {
        //Option 1
          collection.find().toArray(function(err, docs){
                callback (JSON.stringify(docs));
           });

          //Option 2
           var docs = [
               {name:"tingo1", description:"56",_id:2},
               {name:"tingo2", description:"33",_id:3},
               {name:"tingo3", description:"22",_id:4},
               {name:"tingo4", description:"76",_id:5},
               {name:"tingo5", description:"99",_id:6}
           ];   
           callback (JSON.stringify(docs));
  }

    function info(b) {
        // I'm the callback
        console.log(b);
        $scope.items = angular.fromJson(b)
    }

    getData(info);

}]); 

And the Html

<body ng-app="myApp" id="main">

<div class="page page-data ng-scope">


    <section class="panel panel-default" ng-controller="tingoDataCtrl">
    <div class="panel-heading"><span class="glyphicon glyphicon-th"></span> Tingo Data</div>

        <table class="table">
            <thead>
            <th class="col-md-4">
              Name
            </th>
            <th class="col-md-8">
              Description
            </th>
            <th class="col-md-8">
              ID
            </th>
            <th></th>
            <tr>
            </tr>

            </thead>
            <tbody>
            <!-- <tr class="reveal-animation" ng-repeat="item in items | filter:query"> -->
            <tr ng-repeat="item in items | filter:query">
              <td>{{item.name}}</td>
              <td>{{item.description}}</td>
              <td>{{item._id}}</td>

            </tr>
            </tbody>
        </table>
    </section>
</div>
<script src="js/tingo_problem.js"></script>
 </body>

1 Answers1

0

TingoDB is an asynchronous API which will work in the background without stop your app. This means that a syncronous code have no time to wait for an answer and in return it gives undefined.

In your case, you have done a asynchronous call, and it returns correctly the answer to the memory, but too late, the DOM have been updated with undefined already even if your javascript has the data (try console.log to see that it was there).

Angular has a way to be forced to update again the DOM with the new elements of the controller. it is called $apply. And the best way to use it to avoid unexpected behaviours is:

function info(b) {
    // I'm the callback
    console.log(b);
    $scope.items = angular.fromJson(b);
    if (!$scope.$$phase) {
       $scope.$apply(); //forces update the view
    }
}//$scope is NECESARY to be defined in the controler, avoid using it with "ControlerAs"
Ignacio Bustos
  • 1,415
  • 2
  • 17
  • 26