Search code examples
angularjsdatastorepersistent-storageforerunnerdb

Persistence storage in ForerunnerDB not working properly


I am using ForerunnerDB - a NoSQL JSON Document DB for creating a data store on the client (web). This particular library offers a persistence storage option. However, there seems to be something wrong with it. I have included my code below:

App:

(function(){
angular.module("TestApp", ['ui.router', 'LocalStorageModule', 'forerunnerdb']);

})();

Controller:

(function(){
    angular.module("TestApp")
    .controller("FetchGroupsController", function(clientStore, $scope, $http){

        clientStore.getTable("groups").load(function (err, tableStats, metaStats) { 

            if (err) {
                // Load operation was unsuccessful
                console.error("error in pulling collection " + name);
                console.error(err)
            }
            else{
                //there is persisted data corresponding to the requested table
                if(tableStats.foundData && tableStats.rowCount > 0){
                    controller.groups = clientStore.fetchRecords("groups"); //returns an array of objects 
                    console.log("User has " + tableStats.rowCount + " groups");
                    console.log(controller.groups);
                }
                else{//no table for group data persisted */
                    $http({ method: "POST", url: "api/groups/index"})
                    .success(function(data, status){
                        //TODO: handle the activation code
                        if(status == 200){
                            delete data["debug"]; //deleting an unnecessary object from response data
                            clientStore.addList("groups", data);
                            controller.groups = clientStore.fetchRecords("groups");     
                            console.log(controller.groups);
                            clientStore.getTable("groups").save();
                        }
                        else if(status == 403){ //forbidden 
                            controller.messages = data;
                        }
                        else if(status == 401){ //error
                            controller.errors = data;
                        }
                    })
                    ;
                }
            }
        });


    });
})();

Service:

angular.module("TestApp")
.factory('clientStore', function($fdb, $http, localStorageService){

    var clientDB = null;
    var factory = {};

    clientDB = $fdb.db("testDB");

    factory.getDB = function(){
        return clientDB;
    };

    factory.createTable = function(name, pk){
        if(pk != false){
            return clientDB.collection(name, {primaryKey : pk});
        }
        return clientDB.collection(name);
    };

    factory.resetTable = function(name){
        clientDB.collection(name)._data = [];
        clientDB.collection(name).save();
    };

    factory.getTable = function(name){
        return clientDB.collection(name);
    };

    factory.add = function(name, record){ //insert a single object
        clientDB.collection(name).insert(record/*, function(result){
            console.warn(result);
        }*/);
    };

    factory.addList = function(name, records){ //insert a list of objects

        for (record in records){
            clientDB.collection(name).insert(records[record]);
        }

    };

    factory.fetchRecords = function(name){
        return clientDB.collection(name)._data;
    };

    return factory;
});

View:

<div ng-repeat="group in fetchGrpsCtrl.groups" class="row">

    <div class="col-md-12">

        <div class="groups" id="grp-@{{group.id}}" ng-click="fetchGrpsCtrl.setGroup(group)">   

            <div class="details">

                <h5> @{{group.title}}</h5>

            </div>

        </div>

    </div>

</div>

The problem is that the variable controller.group is null in the view, but in the controller, I am getting the expected value when I log it (line 15) out to the console. I thought maybe it was a problem of scope and that the changes made to the variable inside the callback were not being picked up in the view. But that is the not the case because I commented out the line clientStore.getTable("groups").save(); and ran it again and the view was updated perfectly as expected. I cannot figure out why the save() function is erasing the controller.groups variable in the view but is logged out perfectly in the controller.


Solution

  • You are using ForerunnerDB incorrectly. It includes an AngularJS plugin that makes using it with AngularJS very easy, but instead you've written a wrapper of your own that hooks onto the _data property of a collection (something that you shouldn't do because that property is managed internally by ForerunnerDB and can be destroyed and re-created meaning you will have an incorrect reference to an object that might no longer be used by a collection).

    Instead you should use ForerunnerDB in AngularJS as described in the documentation: https://github.com/Irrelon/ForerunnerDB#angularjs-and-ionic-support

    ForerunnerDB includes a helper method called "ng()" that allows you to correctly link data from a collection to your view's scope.

    Also, when using third party javascript libraries, properties with an underscore are generally considered "private" and should not be accessed directly. You should use an accessor method (such as .find() in ForerunnerDB's case) to access data instead. Usually a property that starts with an underscore is a good indication that it is private (not all libraries and programmers follow this convention but many do).