Issue: The property 'executeSql' cannot be read because it is undefined

My custom SQLite module ("DatabaseProvider") contains some essential methods for reading and writing data ("insertActivity" and "getData").

When I invoke the insertActivity() function, everything works smoothly. However, calling the getData() method triggers an unexpected error:

ERROR: TypeError: Cannot read property 'executeSql' of undefined

I am puzzled by this inconsistency since both functions are supposed to be equal, as well as the .ts files from where they are called.

This is how my database.ts looks like:

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);
      });
    });
  }

}

The usage occurs in two sections: "modal-add" and "stats".

Here is my functional modal-add.ts file:

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);
  (...)
  }

}

However, the non-functional stats.ts file raises errors:

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, {
     (...) // logic to generate a chart
  }

}

Any insights or suggestions on how to resolve this issue?

Your assistance is greatly appreciated.

Answer №1

Resolved: I made some beginner mistakes.

After numerous revisions, I realized that the issue was not with my provider method. In the end, I reverted back to its original 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 mistake I made was treating the Promise object as a regular function. I needed to use .then() in my stats.ts:

ionViewDidEnter() {

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

      this.events = res;

      // additional code below
      this.lineChart.config.data.labels = this.events;
      this.lineChart.update();
  });

}

Furthermore, I had to replace ionViewDidLoad() with ionViewDidEnter() due to priority reasons.

Many thanks!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue TS1112: It is not possible to declare a class member as optional

I'm currently working on creating a movie catalog using Angular and Ionic. Within the Movie class, I have properties for id, title, image, and plot. On the initial page of the app, only the id, title, and image are displayed, while the plot is omitte ...

Sending Angular POST requests with Date fields in a specific format for serialization

New to Angular and unsure of the best approach to serializing a Date property when adding an object to a POST request. Taking into account the sample class below: export class MyClass{ public dateProperty: Date; } The service code snippet is as follo ...

Transform JSON into a TypeScript interface with a specialized Date method

Within my Angular 7 project, there is a Post Model defined as follows: export interface PostModel { id: number; created: Date; published: boolean; title: string; } I have implemented an Angular service method aimed at retrieving posts: public g ...

Issue with StencilJS and React output target - It is possible that you will require an extra loader to manage the output generated by these loaders

I've been working on developing basic elements in Stencil for a unique design system. The issue I'm facing is that the components I created function perfectly as custom elements but encounter errors when used as React components. To generate the ...

Creating a header row in a CSV file with Angular 4/Typescript

Currently, I have a code snippet that retrieves data and saves it to a CSV file. However, the issue is that it's writing the data in columns rather than in a header row. I attempted toggling the 'showLabels' option between true and false to ...

What is the reason behind Angular FormControl applying the 'disabled' attribute in the DOM but not the 'required' attribute?

After transitioning my form logic from the template to FormGroup & FormControl objects, I noticed that when a FormControl is disabled in Angular, the 'disabled' attribute for the field is automatically updated in the DOM. However, when I modi ...

Angular and Bootstrap button collections

Incorporating Angular with Bootstrap, we have constructed a button group as shown below: <div class="input-group-append"> <div class="btn-group" role="group"> <button class="btn btn-sm btn-outline-sec ...

Exploring the power of Javascript for number lookup

I am currently working on a coding project using TypeScript and JavaScript to locate a specific number provided by the user within a list. The goal is to display whether or not the number is present in the list when the 'search' button is pressed ...

Creating a new store in Redux Typescript can be challenging due to issues with the middleware

import { configureStore } from "@reduxjs/toolkit"; import { userAPI } from "./api/userAPI"; export const server = import.meta.env.VITE_SERVER; export const store = configureStore({ reducer: { [userAPI.reducerPath]: userAPI ...

A function's behavior will vary depending on whether it is a property of an object or not

I've been observing some peculiar behavior: In a typical scenario, TypeScript usually raises an error when an object contains too many keys, like this: type Foo = { a: string; } const a: Foo = { a: "hello", b: "foo" // Ob ...

Combine an empty array in JavaScript with the existing array to eliminate the current items

Is there a more effective way to merge arrays and update state based on the array received from the server? The array may be empty, which would result in removing all values from the state individually. My objective is to update a new state depending on t ...

Retrieving information from an array using a variable results in undefined, but using a specific number returns the desired object

Currently, in the process of learning TypeScript as my second language, I am encountering some challenges with arrays. I have observed peculiar behavior when accessing the list with a variable as opposed to a hardcoded number. The code snippet in questi ...

Incorporating a JSX Component within a TSX Component results in a compilation error

Recently, I encountered an issue with my typescript-react component named ContractExpenses. The problem arose when I tried to integrate a JSX component called DynamicSelector within it, resulting in the following error: https://i.sstatic.net/BMMir.png Be ...

I'm looking to upload a file in Angular 6 and link it to an API, but it seems to be defaulting to "application/json" type. I need to change it to file format

My approach looks something like this: fileUpload(data){ let headers = new HttpHeaders().set('file', data); headers.append('Content-Type', 'application/file'); let file_upload = { headers: heade ...

Encountering `error TS2554: Constructor expected 0 arguments, received 1` with ts-jest

I've recently delved back into TypeScript and started implementing TDD. I successfully set up ts-jest to run my tests, but I've hit a roadblock with a seemingly simple issue that has me stumped. organization.ts: class Organization implements IO ...

find your way to an angular component within a different module

Currently, I am utilizing this template and running into an issue with navigating from the login component to a different component associated with another module. I have attempted using both this.router.navigate(['myRoute']) and this.router.nav ...

Encountering an error when attempting to store a value in an array of custom types: "Unable to assign properties to undefined (setting 'id')"

My model looks like this: export class SelectedApplicationFeatures { id: number; } In my TypeScript file, I imported the model as shown below: import { SelectedApplicationFeatures } from "src/app/models/selectedApplicationFeatures.model"; selec ...

Leverage the power of forkJoin in JavaScript by utilizing objects or sourcesObject

I'm currently facing an issue with my code snippet below: getInformations().subscribe( informations => { let subs = []; for (const information of informations) { subs.push(getOtherDetails(information.id)); } ...

Can you explain how I can utilize service workers in Angular to access the local storage?

Currently, I am developing an Angular 6 webApp that is designed to be offline first. I have successfully implemented a service worker that can save and retrieve requests and responses. However, I encountered an issue while trying to register a sync event ...

The control of the ThreeJS TransformControl has been relinquished

I am currently working on a project using Typescript within the Autodesk Forge Viewer environment. My goal is to restrict the movement of the ThreeJS transform control to a specific area defined by min and max values for X, Y, and Z coordinates. Additional ...