Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Angular 16 support #293

Closed
mitchgibson opened this issue May 4, 2023 · 19 comments · Fixed by #294
Closed

Angular 16 support #293

mitchgibson opened this issue May 4, 2023 · 19 comments · Fixed by #294
Labels

Comments

@mitchgibson
Copy link

After Angular upgrading from 15 to 16.0.0 I'm getting the following error on app serve:

error NG6002: 'IonicStorageModule' does not appear to be an NgModule class. ... node_modules/@ionic/storage-angular/index.d.ts:6:22 [ng] 6 export declare class IonicStorageModule { [ng] ~~~~~~~~~~~~~~~~~~ [ng] This likely means that the library (@ionic/storage-angular) which declares IonicStorageModule is not compatible with Angular Ivy. Check if a newer version of the library is available, and update if so. Also consider checking with the library's authors to see if the library is expected to be compatible with Ivy

"@ionic/angular": "^7.0.5",
"@ionic/storage-angular": "^3.0.6",
"@capacitor/app": "5.0.0",
"@capacitor/browser": "5.0.0",
"@angular/common": "^16.0.0",
"@angular/core": "^16.0.0",

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    IonicModule.forRoot(),
    IonicStorageModule.forRoot({
      name: ...
    }),
    AppRoutingModule,
    ...
  ],
  providers: [
    ...
  ],
  bootstrap: [AppComponent],
})
@danielehrhardt
Copy link

For now you can copy this file https://github.com/ionic-team/ionic-storage/blob/main/angular/src/index.ts
to you project and use it from there until they fixed it.

@abelhavrl
Copy link

@danielehrhardt copy the file to what location/folder in the project and how to make use of it?

@godenji
Copy link

godenji commented May 5, 2023

Hitting the same issue, seems like v4.0.0-next.1 would solve it, but after upgrading and looking through the node_modules directory for this package, @ionic-storage-angular is missing its dist folder.

@ionic-storage on the other hand is fine. Maybe need to re-publish to NPM?

@sean-perkins
Copy link
Contributor

Hello everyone, thanks for reporting this issue. I have confirmed that the changes on this tag: v4.0.0-next.1 address the problems when upgrading applications to Angular 16.

It looks like our release process may have published from the angular/ directory instead of the angular/dist/ directory. I am working with the team to publish a fix.

@sean-perkins
Copy link
Contributor

Can someone try installing 4.0.0-next.4 and let me know if the problem persists? I've verified locally in another project:

npm install @ionic/storage-angular@4.0.0-next.4

Thanks!

@godenji
Copy link

godenji commented May 5, 2023

Can someone try installing 4.0.0-next.4 and let me know if the problem persists?

Thanks, compiles now in a library project, so package was published correctly.

Not sure yet wrt OP's issue, will try that later today...

EDIT:
looks good "'IonicStorageModule' does not appear to be an NgModule class" error resolved.

Thanks.

@mitchgibson
Copy link
Author

@godenji can confirm, Installing 4.0.0-next.4 fixed the issue. Thank you for the fast resolution.

@sean-perkins
Copy link
Contributor

Awesome, thank you both! I need to meet/discuss with a few team members to coordinate an official 4.0.0 release. I'll leave this issue open in the interim.

@maxbeba
Copy link

maxbeba commented May 6, 2023

I guess 4.0.0. will also resolve #284.
For those who don't want a pre-release, the workaround described there works.

@fromage9747
Copy link

(#293 (comment))

Worked for me too!

@maxbeba
Copy link

maxbeba commented May 7, 2023

4.0.0-next.4 works for me too

@Dantiff
Copy link

Dantiff commented May 18, 2023

Version 4.0.0-next.4 works for me too 🎉

@sean-perkins
Copy link
Contributor

Hello everyone 👋 I've release v4.0.0 which should resolve the pending issues. Please open a new issue if you experience any issues with the new release.

Thanks!

@mdintouch
Copy link

Thanks to everyone who helped fix this!

@PawanSaiKumarGlobibo
Copy link

PawanSaiKumarGlobibo commented Nov 1, 2023

For Angular 16 there is no app module so where we can add IonicStorageModule.forRoot() ?

https://github.com/ionic-team/ionic-storage#with-angular

@mitchgibson
Copy link
Author

For Angular 16 there is no app module so where we can add IonicStorageModule.forRoot() ?

https://github.com/ionic-team/ionic-storage#with-angular

You've set up ionic with standalone components. So I think you can put it in the imports array in your app.component

@rengadevigg
Copy link

I am having issue still while upgrading angular 15 to 16 version.
IonicStorageModule' does not appear to be an NgModule class.(-996002)
index.d.ts(4, 36): This likely means that the library (@ionic/storage) which declares IonicStorageModule is not compatible with Angular Ivy. Check if a newer version of the library is available, and update if so. Also consider checking with the library's authors to see if the library is expected to be compatible with Ivy.
and ionic/storage: 2.3.0 and ionic/storage-angular: 4.0.0

@tirthyakamaldasgupta
Copy link

tirthyakamaldasgupta commented May 6, 2024

I am currently encountering challenges in integrating Ionic Storage within my Ionic 8 (Angular 17) application.

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

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.

@rengadevigg
Copy link

rengadevigg commented May 6, 2024

@tirthyakamaldasgupta private _storage: Storage | null = null; try removing this and directly use the constructor parameter storage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.