Trouble configuring Ionic Storage, TS-Error

Hello,
I’m just getting started developing with Ionic (also generally a noob developer), and I’m having a problem using the storage module.

I started writing an app using the Tabs template and tried to follow the instructions for configuring storage here: Angular App Data Storage Options - Ionic Documentation

This is what my app.module.ts looks like:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { IonicStorageModule } from '@ionic/storage';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule, IonicStorageModule.forRoot],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

I’m getting the following TS error:

Error:(15, 69) TS2322: Type ‘(storageConfig?: StorageConfig) => ModuleWithProviders’ is not assignable to type ‘any | Type | ModuleWithProviders<{}>’.
Property ‘ngModule’ is missing in type ‘(storageConfig?: StorageConfig) => ModuleWithProviders’ but required in type ‘ModuleWithProviders<{}>’.

(My IDE is PHPStorm, its Linter is also hinting at a problem with IonicStorageModule.forRoot)

Here’s my tab2.page.ts:

import { Component } from '@angular/core';
import {Storage} from "@ionic/storage";

@Component({
  selector: 'app-tab2',
  templateUrl: 'tab2.page.html',
  styleUrls: ['tab2.page.scss']
})
export class Tab2Page {

  constructor() {}

  zeichenButtonVisible = true;
  zeichenInputVisible = false;
  rundenButtonVisible = true;
  rundenInputVisible = false;
  oderVisible = true;

  showZeichenInput = () => {
    this.zeichenInputVisible = true;
    this.zeichenButtonVisible = false;
    this.rundenInputVisible = false;
    this.rundenButtonVisible = true;
    this.oderVisible = false;
  }

  showRundenInput = () => {
    this.rundenInputVisible = true;
    this.rundenButtonVisible = false;
    this.zeichenInputVisible = false;
    this.zeichenButtonVisible = true;
    this.oderVisible = false;
  }

  // constructor(private storage: Storage) {}
  //
  // setStorage(){
  //   this.storage.set('numPlayers', '0');
  // }
  //
  // readStorage() {
  //   this.storage.get('numPlayers').then((val)) => {
      //use value for number of player name fields shwon in next tab
  //   }
  // }
}

and this is the page’s html:

<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-title>
      Spiel-Einstellungen
    </ion-title>
  </ion-toolbar>
</ion-header>
<ion-content>
  <ion-input autofocus="true" clear-input="true" inputmode="numeric" type="number">
    Zahl der Spieler:
  </ion-input>

  <ion-item>Geschichtenlänge:</ion-item>
<ion-item id="zeichen-button" *ngIf="zeichenButtonVisible" (click)="showZeichenInput()">
  <ion-button>
    Anzahl Zeichen
   <ion-icon name="arrow-forward-circle-outline"></ion-icon>
  </ion-button>
</ion-item>

  <ion-input id="zeichen-input" *ngIf="zeichenInputVisible" clear-input="true" inputmode="numeric" value="2000" type="number">Anzahl Zeichen</ion-input>
<ion-item *ngIf="oderVisible">oder</ion-item>

  <ion-item id="runden-button" *ngIf="rundenButtonVisible" (click)="showRundenInput()">
    <ion-button>
      Anzahl Runden
      <ion-icon name="arrow-forward-circle-outline"></ion-icon>
    </ion-button>
  </ion-item>
  <ion-input id="runden-input" *ngIf="rundenInputVisible" clear-input="true" inputmode="numeric" type="number">Anzahl Runden</ion-input>

  <ion-button [routerLink]="['/tab3']">Speichern</ion-button>
</ion-content>

I’m guessing, I’ve just not completed the configuration yet, but I’m kinda lost right now.
I haven’t understood from the documentation: Is Storage configured for the whole app, or do I need to inject it into every page that stores data? Which files do the configurations go into?
Sorry for all the noob questions, thanks for any hints!

Admittedly the error message you receive when you write this is terrible, but you need IonicStorageModule.forRoot() here - call the function, don’t just provide a reference to it.

Yes.

No, but IMHO no page should ever store data, so this is moot. Do all interaction with storage in services, not pages. That centralizes things, making them easier to maintain.

Assuming you mean configuration for Ionic Storage, in the forRoot call as documented here.

1 Like
  1. The Tabs template has a folder und src/app called assets - is that where services should go? Otherwise, what’s the recommended location for a service in Ionic?
  2. Then how do I point form on a page at that service to save that user input to Storage?

No, that’s for static files like JSON and images.

I can’t speak for Ionic, but I organize my projects by feature, so sometimes that means services live in their own folder under src/app, and sometimes they share one with some components that are tightly related to them.

You inject it as described in tour of heroes 4.

I’m sorry, there’s a lot of new terminology here and I have trouble understanding it all - and applying the examples to my code.
It seems to say I should run ng generate service in order to provide the service?
Does that apply even if I already ran ionic generate service?

-Also I was thinking I should maybe write a class that bundles the information that user enters on one page into an object, and separate that from the storage service?

No. Generators are totally optional. I personally never use them at all.

Reasonable people can disagree about this, but I emphatically would not do that. I would make an interface, but not a class. For more rationale, see this, this, and even this oldie.