Dani
Dani

Reputation: 4177

Lazy loading - Providers and modules

I'm moving my app to lazy loading. I'm done with pages, pipes and directives but now it's the turn of providers/services and some other modules.

This was my app.module:

...
import { FileUploadModule } from "ng2-file-upload";
import { CloudinaryModule } from "@cloudinary/angular-5.x";
import * as cloudinary from "cloudinary-core";
import { ImageUploadProvider } from "../services/image-upload/image-upload";
...
imports: [
 ...
 FileUploadModule,
 CloudinaryModule.forRoot(cloudinary, {
   cloud_name: "cloudName",
   upload_preset: "cloudCode"
  }),
  ...
]
providers: [
 ...
 ImageUploadProvider
  ...
]

Now, these references are removed from this file.

I need all of this on my new-recipe component. For that I added this into new-recipe.module:

import { ImageUploadProvider } from "../../services/image-upload/image-upload";
...
providers: [
    ImageUploadProvider
  ]

What else do I need? I also created a image-upload.module but not sure if this is correct:

import { NgModule, ModuleWithProviders } from '@angular/core';
import { FileUploadModule } from "ng2-file-upload";
import { CloudinaryModule } from "@cloudinary/angular-5.x";
import * as cloudinary from "cloudinary-core";
import { ImageUploadProvider } from '../services/image-upload/image-upload';

@NgModule({
  imports: [
    FileUploadModule,
    CloudinaryModule.forRoot(cloudinary, {
      cloud_name: "cloudName",
      upload_preset: "cloudId"
    })
  ],
  exports: [
    CloudinaryModule
  ]
})

export class ImageUploadProviderModule {
  static forRoot(): ModuleWithProviders {
    return {
      ngModule: ImageUploadProviderModule,
      providers: [ImageUploadProvider] // <-- is this necessary?
    };
  }
}

Do I need to import this new module inside new-recipe.module and remove the provider reference? How can I access then from my functions in new-recipe to this.imageUploadProvider?

Upvotes: 2

Views: 2918

Answers (2)

Danish Aziz
Danish Aziz

Reputation: 483

Assuming you are lazily loading your recipe module, and new-recipe component is declared in your Recipe module which will use the image imageUploadProvider and this provider will also be used by other components, here is the possible solution:

  • If you need the service/Provider only in components inside your recipe module, then you need to remove import of the service from the providers array in app.module, import the service in your Recipe Module like you have done, provide it in it's providers array. After this to use the service simply import the service in your components(which are part of your recipe module), declare the service in the component's constructor and you'll be good to go, repeat the same step for any other component inside Recipe module and they will receive the same instance.
  • Now If you want to use the imageUploadProvider in any component across any module and receive the same instance then you'll have to provide it in the root module. For that, you simply need to import the service in your root module(app.module) and declare it in the providers array like you did in your app module earlier:

    import { ImageUploadProvider } from "../../services/image-upload/image-upload"; ... providers: [ ImageUploadProvider ]

After this, you will be able to import the service in any component you want and declare it in their constructor and use them. You should not import this service into any other module and mention it in their providers array, this will create a separate instance. If you are doing lazy loading properly and import & declare the service correctly in your components then this solution should work. You can also give a read about shared services in your free time.

Upvotes: 1

danday74
danday74

Reputation: 56936

If you are using Angular 6 (might be in 5 too but I don't think so) you might want to simply use:

@Injectable({
  providedIn: 'root'
})

I believe this will load services on demand without them being provided in any providers array which should make your life a whole lot easier. This provides a singleton service available to the whole app. Appropriate for stateless services.

You can also specify a providedIn: moduleName if that works better for you.

Once again, you don't have to list the service in the module's providers array.

See https://angular.io/tutorial/toh-pt4 for a bit more info. Search for providedIn

Upvotes: 1

Related Questions