[SOLVED] Can't get data from SQLite db (but I can write to it) with a provider


#1

Hi

I’ve got a SQLite provider (“DatabaseProvider”) with some read and write methods (“insertActivity” and “getData”).

When I call my insertActivity() method all goes well;
but when I call getData() it gives me this error:

ERROR: TypeError: Cannot read property ‘executeSql’ of undefined

I can’t understand why, because I think methods are identical and .ts files from where I call them, too.

Here’s my database.ts:

import { Injectable } from '@angular/core';
import { SQLite, SQLiteObject } from '@ionic-native/sqlite';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
 
@Injectable()
export class DatabaseProvider {
  // private storage:  SQLite;
  public db:       SQLiteObject;
  public isOpen:   boolean;
  public storage:  any;

  constructor(
    public http:      Http,
    public database:  SQLite,

  ) {

    if (!this.isOpen) {
        // create db and tables

          this.database = new SQLite();
          this.database.create({name: 'RLSDB', location: 'default'})
          .then((db: SQLiteObject) => {
            this.storage = db;
            db.executeSql('create table if not exists LOGIN (id INTEGER PRIMARY KEY AUTOINCREMENT, sid TEXT, username TEXT, password TEXT, email TEXT, timestamp TEXT)', {}).then((data) => {
              this.isOpen = true;
              console.log('TABLE CREATED: ', data);
            }, (error) => {
              console.error("Unable to execute sql", error);
            });
          }).then(() => {
            this.storage.executeSql('create table if not exists ACTIVITIES (id INTEGER PRIMARY KEY AUTOINCREMENT, activity_name TEXT, activity_datetime TEXT)', {});
            this.isOpen = true;
          }
        );
    }
  }
 
  public getData() {

    return new Promise((resolve, reject) => {
      this.storage.executeSql('SELECT * from ACTIVITIES', []).then((data) => {
        let activityValues = [];
        if (data.rows.length > 0) {
          for(let i=0; i <data.rows.length; i++) {
            activityValues.push(data.rows.item(i).activity_datetime);
          }
        }
        return resolve(data);
    }, (error) => {
      return reject(error);
    });
  });


  }

  public insertActivity(
    RLSActivity: string,
    RLSActivityDatetime: any ) {
      return new Promise((resolve, reject) => {
        this.storage.executeSql("INSERT INTO ACTIVITIES (activity_name, activity_datetime) VALUES (?, ?)", [RLSActivity, RLSActivityDatetime]).then((data) => {
          return resolve(data);
      }, (error) => {
        return reject(error);
      });
    });
  }
 
}

I use it on two pages: “modal-add” and “stats”.

my modal-add.ts, which works perfectly:

import { Component } from '@angular/core';
import { NavController  } from 'ionic-angular';
import { IonicPage, NavParams, ViewController } from 'ionic-angular';
import { DiaryPage } from '../diary/diary';
import {Validators, FormBuilder, FormGroup } from '@angular/forms';
import { DatabaseProvider } from '../../providers/database/database';

@IonicPage()
@Component({
  selector: 'page-modal-add',
  templateUrl: 'modal-add.html',
})
export class ModalAddPage {

  private activityForm: FormGroup;

  constructor(
    public navParams: NavParams,
    private view: ViewController,
    private navCtrl: NavController,
    private formBuilder: FormBuilder,
    public database: DatabaseProvider
  ) {
    this.activityForm = this.formBuilder.group({
          title: [''],
          date: [''],
        });

   }
 
  closeModal(){

    const inputData = {
      title: this.activityForm.value.title,
      date: this.activityForm.value.date,
    };
   
    this.database.insertActivity(inputData.title, inputData.date);
  (...)
  }
 
}

and my stats.ts, which returns error:

import { Component, ViewChild } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { DiaryPage } from '../diary/diary';
import { DatabaseProvider } from '../../providers/database/database';
import { Chart } from 'chart.js';

@IonicPage()
@Component({
  selector: 'page-stats',
  templateUrl: 'stats.html'
})
export class StatsPage {

  @ViewChild('lineCanvas') lineCanvas;

  lineChart: any;
  events: any;

  constructor(
    public navCtrl: NavController,
    public navParams: NavParams,
    private db: DatabaseProvider
  ) {

  } 

  ionViewDidLoad() {
   
    this.events = this.db.getData();
    this.lineChart = new Chart(this.lineCanvas.nativeElement, {
     (...) // stuff to create a chart
  }

}

Any ideas?

Thank you in advance for your help.


#2

Solved: I’ve done some bad noob mistakes.

There were no problems inside my provider method and after a thousand changes I reverted to its initial structure:

public getData() {

  return new Promise((resolve, reject) => {
    this.storage.executeSql('SELECT * from ACTIVITIES', []).then((data) => {
      let activityValues = [];
      if (data.rows.length > 0) {
        for(let i=0; i <data.rows.length; i++) {
          activityValues.push(data.rows.item(i).activity_datetime);
        }
      }
      // alert(activityValues); // contains data
      resolve(activityValues);
    }, (error) => {
      reject(error);
    })
  });
}

The newbie thing was the attempt to pass data as the Promise obj were a normal function. In fact I had to use .then() in my stats.ts:

ionViewDidEnter() {

  this.db.getData().then( res => {

      this.events = res;
      
      // some new stuff below
      this.lineChart.config.data.labels = this.events;
      this.lineChart.update();
  });

}

and as you can see, I had to substitute ionViewDidLoad() with ionViewDidEnter() for priority reasons.

Thank you.