Hi,
I am trying to follow Ionic cli’s “super” template on an app that uses lazy load.
However I don’t need to lazy load the settings that use ionic storage (https://ionicframework.com/docs/storage/).
When using the storage module directly everything works fine, however when using it inside a settings.ts provider just like the ionic “super” template (so I can add some business logic to populate the settings from an http call when the app starts), this is when things stop working.
Here is my app.module.ts:
import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { HttpModule } from "@angular/http";
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { IonicStorageModule } from '@ionic/storage';
import { MyApp } from './app.component';
import { SettingsProvider } from './../providers/settings/settings';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
export function provideSettings(storage: Storage) {
return new SettingsProvider(storage, {
Testkey: 'Hello Settings'
});
}
@NgModule({
declarations: [
MyApp
],
imports: [
BrowserModule,
HttpModule,
IonicModule.forRoot(MyApp),
IonicStorageModule.forRoot()
],
bootstrap: [IonicApp],
entryComponents: [
MyApp
],
providers: [
StatusBar,
SplashScreen,
{ provide: ErrorHandler, useClass: IonicErrorHandler },
{ provide: SettingsProvider, useFactory: provideSettings, deps: [Storage] },
]
})
export class AppModule {}
and the settings provider is the exact replica from the “super” template, just changed the name to settingsProvider instead of settings:
import { Injectable } from '@angular/core';
import { Storage } from '@ionic/storage';
/**
* A simple settings/config class for storing key/value pairs with persistence.
*/
@Injectable()
export class SettingsProvider {
private SETTINGS_KEY: string = '_settings';
settings: any;
_defaults: any;
_readyPromise: Promise<any>;
constructor(public storage: Storage, defaults: any) {
this._defaults = defaults;
}
load() {
return this.storage.get(this.SETTINGS_KEY).then((value) => {
if (value) {
this.settings = value;
return this._mergeDefaults(this._defaults);
} else {
return this.setAll(this._defaults).then((val) => { this.settings = val; })
}
});
}
_mergeDefaults(defaults: any) {
for (let defaultSettings in defaults) {
if (!(defaultSettings in this.settings)) {
this.settings[defaultSettings] = defaults[defaultSettings];
}
}
return this.setAll(this.settings);
}
merge(settings: any) {
for (let setting in settings) {
this.settings[setting] = settings[setting];
}
return this.save();
}
setValue(key: string, value: any) {
this.settings[key] = value;
return this.storage.set(this.SETTINGS_KEY, this.settings);
}
setAll(value: any) {
return this.storage.set(this.SETTINGS_KEY, value);
}
getValue<T>(key: string): Promise<T> {
return this.storage.get(this.SETTINGS_KEY).then(settings => { return settings[key] as T; });
}
save() {
return this.setAll(this.settings);
}
get allSettings() {
return this.settings;
}
}
then I’d inject it to a page like so:
...
import { SettingsProvider } from './../../providers/settings/settings';
@IonicPage({
name: 'MyPage'
})
@Component({
selector: 'my-page',
templateUrl: 'mypage.html'
})
export class MyPage {
items: Array<Item>;
constructor(public navCtrl: NavController, private api: ApiProvider, private settings: SettingsProvider) {
this.api.get<Array<Item>>("items.json").subscribe(response => this.items = response);
this.settings.load().then(() => {
this.settings.setValue("Testkey", "TestValue");
this.settings.getValue('Testkey').then(val => {
console.log(val);
});
});
}
...
}
I get this error on lazy loaded pages:
Runtime Error
Uncaught (in promise): Error: No provider for Storage! Error: No provider for Storage! at injectionError (http://localhost:8100/build/vendor.js:1590:86) at noProviderError (http://localhost:8100/build/vendor.js:1628:12) at ReflectiveInjector_._throwOrNull (http://localhost:8100/build/vendor.js:3129:19) at ReflectiveInjector_._getByKeyDefault (http://localhost:8100/build/vendor.js:3168:25) at ReflectiveInjector_._getByKey (http://localhost:8100/build/vendor.js:3100:25) at ReflectiveInjector_.get (http://localhost:8100/build/vendor.js:2969:21) at AppModuleInjector.get (ng:///AppModule/module.ngfactory.js:252:111) at AppModuleInjector.getInternal (ng:///AppModule/module.ngfactory.js:400:58) at AppModuleInjector.NgModuleInjector.get (http://localhost:8100/build/vendor.js:3936:44) at HomePageModuleInjector.NgModuleInjector.get (http://localhost:8100/build/vendor.js:3937:52)
Ionic Framework: 3.6.1
Ionic App Scripts: 2.1.3
Angular Core: 4.1.3
Angular Compiler CLI: 4.1.3
Node: 8.2.1
OS Platform: Windows 10
Navigator Platform: Win32
User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.91 Safari/537.36
I tried many things like adding the settings provider it to the lazy loading page module (which I think is wrong), which didn’t work, since it’s already loaded in the app module.
Also tried just adding it like a normal provider:
this:
providers: [
...
SettingsProvider,
]
instead of this
providers: [
...
{ provide: SettingsProvider, useFactory: provideSettings, deps: [Storage] },
]
also didn’t work.
I am fairly new to Ionic, I would really appreciate any help or explanation.
Thanks