Reputation: 9
I am encountering the following error in my browser console: ERROR NullInjectorError: NullInjectorError: No provider for Storage!
, upon attempting to configure Ionic Storage within Ionic 8 (Angular 17). Any guidance on the correct setup procedure would be greatly appreciated. Thank you in advance.
I have adhered to the official documentation guidelines for implementing Ionic Storage within an independent service. The following is the content of the storage.service.js file:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class StorageService {
private _storage: Storage | null = null;
constructor(private storage: Storage) {
this.init();
}
async init() {
const storage = await this.storage['create']();
this._storage = storage;
}
public async get(key: string) {
const value = await this._storage?.['get'](key);
return value;
}
public async set(key: string, value: any) {
await this._storage?.['set'](key, value);
}
}
I am utilizing this service within another service for authentication-related purposes. The following is the content of the auth.service.js file:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { StorageService } from './storage.service';
interface Credentials {
username: string;
password: string;
}
export interface AuthResponse {
auth_token: string;
}
@Injectable({
providedIn: 'root',
})
export class AuthService {
constructor(
private httpClient: HttpClient,
private storageService: StorageService
) {}
async getAuthToken(): Promise<string> {
const token = await this.storageService.get('token');
return token;
}
async isAuthenticated(): Promise<boolean> {
const token = await this.getAuthToken();
if (token) {
return true;
}
return false;
}
authenticate(credentials: Credentials): Observable<AuthResponse> {
return this.httpClient.post<AuthResponse>(
`${import.meta.env['NG_APP_API_BASE_URL']}/${
import.meta.env['NG_APP_API_PREFIX']
}/token/login`,
credentials
);
}
async processPostLoginOps(token: string): Promise<void> {
await this.storageService.set('token', token);
const authenticated = await this.isAuthenticated();
if (authenticated) {
throw new Error('Unable to login');
}
}
}
Finally I am integrating this service within a page. The following is the content of the login.page.ts file:
import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import {
FormBuilder,
FormGroup,
FormsModule,
ReactiveFormsModule,
Validators,
} from '@angular/forms';
import { Router } from '@angular/router';
import {
IonButton,
IonCard,
IonCardContent,
IonCol,
IonContent,
IonGrid,
IonHeader,
IonInput,
IonItem,
IonList,
IonNav,
IonRow,
IonTitle,
IonText,
IonToolbar,
} from '@ionic/angular/standalone';
import { LoadingController, ToastController } from '@ionic/angular';
import { AuthService, AuthResponse } from 'src/app/services/auth.service';
import { Capacitor } from '@capacitor/core';
@Component({
selector: 'app-login',
templateUrl: './login.page.html',
styleUrls: ['./login.page.scss'],
standalone: true,
imports: [
IonButton,
IonCard,
IonCardContent,
IonCol,
IonContent,
IonGrid,
IonHeader,
IonInput,
IonItem,
IonList,
IonNav,
IonRow,
IonTitle,
IonText,
IonToolbar,
CommonModule,
FormsModule,
ReactiveFormsModule
],
})
export class LoginPage implements OnInit {
form!: FormGroup;
disabled: boolean = true;
loadingOverlay!: HTMLIonLoadingElement;
errorToast!: HTMLIonToastElement;
constructor(
private router: Router,
private formBuilder: FormBuilder,
private loadingController: LoadingController,
private toastController: ToastController,
private authService: AuthService
) {}
async ngOnInit(): Promise<void> {
this.initForm();
this.subscribeToFormChanges();
await this.setOrResetLoadingOverlay();
await this.setToasts();
}
private async setToasts() {
this.errorToast = await this.toastController.create({
duration: 1500,
position: 'bottom'
});
}
private async setOrResetLoadingOverlay() {
this.loadingOverlay = await this.loadingController.create({});
}
initForm(): void {
this.form = this.formBuilder.group({
username: ['', Validators.required],
password: ['', Validators.required],
});
}
subscribeToFormChanges(): void {
this.form.statusChanges.subscribe((status) => {
if (status === 'VALID') {
this.disabled = false;
} else {
this.disabled = true;
}
});
}
async authenticate() {
this.loadingOverlay.message = 'Logging in';
await this.loadingOverlay.present();
this.authService
.authenticate({
username: this.form.value.username,
password: this.form.value.password,
})
.subscribe({
next: async (response: AuthResponse) => {
this.loadingOverlay.dismiss();
this.loadingOverlay.message = 'fdnfgnfgn';
this.loadingOverlay.present();
try {
this.authService.processPostLoginOps(response.auth_token);
this.router.navigate(['/']).then(() => window.location.reload());
} catch (error) {
await this.setOrResetLoadingOverlay();
this.errorToast.message = 'Unable to login';
this.errorToast.present();
}
},
error: async (error: any) => {
this.loadingOverlay.dismiss();
await this.setOrResetLoadingOverlay();
this.errorToast.message = 'Unable to login';
this.errorToast.present();
},
});
}
register(): void {
this.router.navigate(['/register']);
}
}
Upvotes: 0
Views: 537
Reputation: 26
I think you need to declare storage in app providers:
import { IonicStorageModule } from '@ionic/storage-angular';
@NgModule({
imports: [
IonicStorageModule.forRoot()
]
})
export class AppModule { }
You can find all setup step at https://github.com/ionic-team/ionic-storage
Upvotes: 1