0

after all of my problems with SQLite, I wanted to use a different solution for my Ionic app. LokiJS was often mentioned, so I tried it. But also with LokiJS I have no luck.

At the moment I have a very basic code, which should work without problems:

.controller('ProjectsController', ['$scope', '$state', '$ionicPlatform', function($scope, $state, $ionicPlatform) {
  var pcVm = this;

  var db;
  var projects1;

  $ionicPlatform.ready(function(){

    var idbAdapter = new LokiIndexedAdapter('loki');
    db = new loki('lkr-v4', {
      autoload: true,
      autoloadCallback : getAllProjects,
      autosave: true,
      autosaveInterval: 10000,
      adapter: idbAdapter
    });

    function getAllProjects() {
      var options = {};
      db.loadDatabase(options, function() {
        projects1 = db.getCollection('projects'); // GET
        if (!projects1) {
          projects1 = db.addCollection('projects'); // ADD
        }
        console.log('Databaseinformation');
        console.log(db);
        console.log('Collectioninformation');
        console.log(projects1);
      });
    }

    console.log('Insert something');
    projects1.insert({ name : 'odin' });
  }); // End of .ready()

But I get always the message:

ionic.bundle.js:26794 TypeError: Cannot read property 'insert' of undefined
    at controllers.js:309
    at ionic.bundle.js:56230
    at Object.ready (ionic.bundle.js:2140)
    at Object.ready (ionic.bundle.js:56223)
    at new <anonymous> (controllers.js:283)
    at Object.instantiate (ionic.bundle.js:18010)
    at $controller (ionic.bundle.js:23412)
    at self.appendViewElement (ionic.bundle.js:59900)
    at Object.render (ionic.bundle.js:57893)
    at Object.init (ionic.bundle.js:57813)(anonymous function) @ ionic.bundle.js:26794(anonymous function) @ ionic.bundle.js:23507$broadcast @ ionic.bundle.js:30720$state.transition.resolved.then.$state.transition @ ionic.bundle.js:52157processQueue @ ionic.bundle.js:29127(anonymous function) @ ionic.bundle.js:29143$eval @ ionic.bundle.js:30395$digest @ ionic.bundle.js:30211$apply @ ionic.bundle.js:30503done @ ionic.bundle.js:24824completeRequest @ ionic.bundle.js:25022requestLoaded @ ionic.bundle.js:24963
controllers.js:301 Databaseinformation

Please help. Maybe I have the same problem wit SQLite and LokiJS? But I can't find the problem...

Thanks, Christian.


UPDATE - 2016-08-05

So, I spent again hours of hours with searching, trying, and always ending up with the same errors. I am wondering why all of the tutorials look the same, and seem to work, but for me it's impossible to get it running.

I completely rewrote my factory:

(function() {
  'use strict';

  angular.module('lkr-v4')

    .factory('PersistenceService', ['$q', 'Loki', PersistenceService]);

      function PersistenceService($q, Loki) {
        // Needed variables
        var lkrDb; // Database
        var projects; // Collection of JSON strings

        // Accessible Members Up Top
        // https://github.com/johnpapa/angular-styleguide/tree/master/a1#style-y052
        var pService = {
          initDB: initDB,
          getAllProjects: getAllProjects,
          addProject: addProject,
          updateProject: updateProject,
          deleteProject: deleteProject
        };
        return pService;

        // Initialization of the database
        function initDB() {
          var idbAdapter = new LokiIndexedAdapter('loki');
          lkrDb = new loki('lkr-v4', {
            autoload: true,
            autoloadCallback: getAllProjects,
            autosave: true,
            autosaveInterval: 10000,
            adapter: idbAdapter
          });
        }

        // Function to return a collection of JSON strings (all found projects) in the LokiJS database file
        function getAllProjects() {
          // What is $q? See https://docs.angularjs.org/api/ng/service/$q
          return $q(function (resolve, reject) {
            var options = {};
            lkrDb.loadDatabase(options, function () {
              projects = lkrDb.getCollection('projects'); // GET!
              // If the database file is empty
              if (!projects) {
                projects = lkrDb.addCollection('projects'); // ADD!
              }
              resolve(projects.data);
            });
          });
        }

        // Function to add a project
        function addProject(project) {
          if(lkrDebug) {
            console.log('Inside of addProject from the factory');
            console.log('This is the projects object');
            console.log(this.projects);
            console.log('This is the given value of the new project');
            console.log(project);
          }
          projects.insert(project);
        }

        // Function to update a project
        function updateProject(project) {
          projects.update(project);
        }

        // Function to delete a project
        function deleteProject(project) {
          projects.remove(project);
        }

      } // End of function PersistenceService

})(); // End of IIFE

I call the PersistenceService.initDB() in the run() of my app.js. THIS WORKS!

All of my pages (4) have their own controller, used over controller as. In the controller of my first page, I tried this code:

  // Test #1: Get data
  PersistenceService.getAllProjects().then(function(projects) {
    pcVm.projects = projects;
    if(lkrDebug) {
      console.log('Inside of getAllProjects().then() from the controller');
      console.log('This is the project object from the PersistenceService');
      console.log(projects);
      console.log('And this ist the pcVm.projects object from the controller');
      console.log(pcVm.projects);
    }
  });

IT WORKS! I can see the correct information in the consloe, and I don't get any error.

The next code is placed directly after the code above in the same controller:

  // Test #2: Add a project
  PersistenceService.addProject({ name : 'odin' });

And it produces the following lines (and erros) on the console

Inside of addProject from the factory
persistence.services.js:65 This is the projects object
persistence.services.js:66 undefined
persistence.services.js:67 This is the given value of the new project
persistence.services.js:68 Object {name: "odin"}
ionic.bundle.js:26794 TypeError: Cannot read property 'insert' of undefined
    at Object.addProject (persistence.services.js:70)
    at new ProjectsController (projects.controller.js:31)
    at Object.instantiate (ionic.bundle.js:18010)
    at $controller (ionic.bundle.js:23412)
    at self.appendViewElement (ionic.bundle.js:59900)
    at Object.render (ionic.bundle.js:57893)
    at Object.init (ionic.bundle.js:57813)
    at self.render (ionic.bundle.js:59759)
    at self.register (ionic.bundle.js:59717)
    at updateView (ionic.bundle.js:65398)(anonymous function) @ ionic.bundle.js:26794(anonymous function) @ ionic.bundle.js:23507$broadcast @ ionic.bundle.js:30720$state.transition.resolved.then.$state.transition @ ionic.bundle.js:52157processQueue @ ionic.bundle.js:29127(anonymous function) @ ionic.bundle.js:29143$eval @ ionic.bundle.js:30395$digest @ ionic.bundle.js:30211$apply @ ionic.bundle.js:30503done @ ionic.bundle.js:24824completeRequest @ ionic.bundle.js:25022requestLoaded @ ionic.bundle.js:24963
projects.controller.js:22 Inside of getAllProjects().then() from the controller
projects.controller.js:23 This is the project object from the PersistenceService
projects.controller.js:24 [Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object]
projects.controller.js:25 And this ist the pcVm.projects object from the controller
projects.controller.js:26 [Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object]

That's a little bit strange, because for me it looks like addProject() is called bevore getAllProjects()?

So I added the line console.log(lkrDb); in the addProject-function, to see if the database is loaded, and I did some more tests. It turned out, that the the initDB in the app.js is working, and that the addProject-function can also work with the opened database.

My conclusion is, that I do something wrong in the controller, or with the getAllProjects-function!?

I'll keep on searching, but I would be realy thankfull for any hint...

Thanks, Christian.

cjs1976
  • 35
  • 2
  • 8

2 Answers2

0

projects1 is not initialised properly you have to call projects1.insert() only after db.loadDatabase() callback

This should work. This is just a spike, try using factory for database operations. And go through javascript variable scope so that you don't face this problem again.

db.loadDatabase(options, function() {
  projects1 = db.getCollection('projects');
  if (!projects1) {
    projects1 = db.addCollection('projects');
  }
  projects1.insert({name: 'odin'});      

  });

Hope it helps, Happy Coding :)

Update: Please update the question with your actual problem.

Rathan
  • 79
  • 1
  • 2
  • 11
  • Hi Rathan! Thank you, your example seems to work. I wanted to do it over a factory like in this tutorial http://gonehybrid.com/how-to-use-lokijs-for-local-storage-in-your-ionic-app, but it never worked. Someone in the chat told me to try it first on the very basic way, and then find the problem over trial and error. Now it works, and I think I understood why, but I have no idea why it works in the tutorial, but not with my code... – cjs1976 Aug 04 '16 at 09:44
  • What error are you getting? If you mention log here then I could help you debug. – Rathan Aug 04 '16 at 11:36
  • I spent again some hours. I try now to change the style of my app as recommended by John Papa (Angular 1 Style Guide), and I found a lot of mistakes already, but I think they were not related to my problem. But because of this, I also rewrote my PersistenceService factory. But I end up with the same problem. The initialization works, the getAll works, but insert/update/delete they don't. – cjs1976 Aug 04 '16 at 14:49
  • Javascript execution stack (control flow) is little different compare to other languages, so first try to understand control flow then you'll know why variables are not initialising this might help in understanding that: https://youtu.be/8aGhZQkoFbQ, do some research on these lines. If nothing helping update the question – Rathan Aug 04 '16 at 15:10
  • i watched the video twice. i simply don't understand it. and more confusing is, why are the tutorials working (i found a lot with the same style), but i get the error? and yes, in the console it looks like the insert would be done before the rest of my code. i don't know why. i tried to google for it, but i couldn't find a for me understandable explanation. – cjs1976 Aug 05 '16 at 08:41
0

Now I understand the promises thing! This helped me a lot: http://andyshora.com/promises-angularjs-explained-as-cartoon.html

But, even if this is something I have to really take care of, this is not the problem. The problem is based on the tutorials I used. I don't know why and how, but the tutorilas work, and my app doesn't simply because: as long as I don't call the getAllProjects() function, the projects1 variable has no data. The autoloadCallback doesn't call the function automatically!? I opened an Issue at the LokiJS project to ask what I do wrong, or if this is not the idea of the autoloadCallback.

When I have a complete working solution, I will post it here...

cjs1976
  • 35
  • 2
  • 8