To use the provider class methods from another module in the current module controller,
- First, you have to export the
provider
class that needs to be used in other modules by adding the provider class in theexports
array and theproviders
array of the@Module
decorator function in its module definition file. - Secondly, you have to import the
module
class that has the provider class methods to be used in the current module definition file. You can do this by adding the module class name to theimports
array of the@Module
decorator function in the module in which you are going to use the provider class methods. - Finally, you can use the imported
provider
class methods in the controller class methods after the initialization of the provider class.
TL;DR
Filepath: /image/image.service.ts
import { Injectable } from "@nestjs/common";
@Injectable()
export class ImageService {
// the method we intend to use on another module
getRandomImage() {
return "https://picsum.photos/200";
}
}
Filepath: /image/image.module.ts
import { Module } from "@nestjs/common";
// import the image service provider class
import { ImageService } from "./image.service";
@Module({
imports: [],
controllers: [],
providers: [ImageService], // add `ImageService` provider here
exports: [ImageService], // to export the `ImageService` class, add the class here
})
export class ImageModule {}
Filepath: /greet/greet.module.ts
import { Module } from "@nestjs/common";
import { GreetController } from "./greet.controller";
import { ImageModule } from "../image/image.module";
@Module({
/*
add the `ImageModule` module here 👇🏽, so that the
provider class methods can be used in the current module.
*/
imports: [ImageModule],
controllers: [GreetController],
providers: [],
})
export class GreetModule {}
Filepath: /greet/greet.controller.ts
import { Controller, Get } from "@nestjs/common";
import { ImageService } from "../image/image.service";
@Controller("/greet")
export class GreetController {
// declaring and initializing the `ImageService` provider
// class using the fast and short way in the `constructor` method itself
constructor(private imageService: ImageService) {}
// The `Get()` decorator function will instruct the
// Nestjs runtime to use the `getImage()`
// method for a `GET` of `/greet` endpoint.
@Get()
getImage() {
// using the `getRandomImage()` method from the
// instance of the `ImageService` provider class.
return this.imageService.getRandomImage();
}
}
Filepath: /app.module.ts
import { Module } from "@nestjs/common";
import { GreetModule } from "./greet/greet.module";
@Module({
imports: [GreetModule], // <- add GreetModule here
})
export class AppModule {}
Confused? 🤔. See the example with 2 modules below to get a better idea.
For example, let's say we have 2 modules called image
and greet
in our Nestjs Application.
The image
module contains a service provider
class that has a method called getRandomImage()
that returns the url of a random image.
The service provider
class looks like this,
Filepath: /image/image.service.ts
import { Injectable } from "@nestjs/common";
@Injectable()
export class ImageService {
// the method we intend to use on another module
getRandomImage() {
return "https://picsum.photos/200";
}
}
NOTE: To know more about creating service Provider
classes in Nestjs, see the blog on What is the best way to do complex business logic computations for any API in Nestjs?.
The directory structure of the image
and greet
modules now looks like this,
- src
- image
- - image.service.ts
- greet
- - greet.controller.ts
- - greet.module.ts
Now let's make the image
into a module by creating a class called ImageModule
in a file called image.module.ts
in the current directory and then use the @Module()
decorator function from the @nestjs/common
module.
It can be done like this,
Filepath: /image/image.module.ts
import { Module } from "@nestjs/common";
@Module({
imports: [],
controllers: [],
providers: [],
exports: [],
})
export class ImageModule {}
As you can see from the above code, we have made the image module file, but haven't exported the ImageService
class that needs to be used by other modules.
To export the ImageService
class, we can add the ImageService
class name to the exports
array as well as the providers
array of the @Module()
decorator function.
It can be done like this,
Filepath: /image/image.module.ts
import { Module } from "@nestjs/common";
// import the image service provider class
import { ImageService } from "./image.service";
@Module({
imports: [],
controllers: [],
providers: [ImageService], // add `ImageService` provider here
exports: [ImageService], // to export the `ImageService` class, add the class here
})
export class ImageModule {}
The directory structure of the image
and greet
modules now looks like this,
- src
- image
- - image.service.ts
- - image.module.ts
- greet
- - greet.controller.ts
- - greet.module.ts
The greet
module file looks like this,
Filepath: /greet/greet.module.ts
import { Module } from "@nestjs/common";
import { GreetController } from "./greet.controller";
@Module({
imports: [],
controllers: [GreetController],
providers: [],
})
export class GreetModule {}
If you look at the above code, the imports
array is empty and we won't be able to use the image
module's getRandomImage()
method inside this module.
We aim to use the getRandomImage()
method from the image
module in the greet
module. To do that, we have to first import the image
module and add it to the imports
array of the @Module()
decorator function in the GreetModule
class.
It can be done like this,
Filepath: /greet/greet.module.ts
import { Module } from "@nestjs/common";
import { GreetController } from "./greet.controller";
import { ImageModule } from "../image/image.module";
@Module({
/*
add the `ImageModule` module here 👇🏽, so that the
provider class methods can be used in the current module.
*/
imports: [ImageModule],
controllers: [GreetController],
providers: [],
})
export class GreetModule {}
Now to test it let's go into the getImage()
method of the GreetController
controller class of the greet
module and use the getRandomImage()
method from the ImageService
class.
NOTE: We can use the method after initialization of the ImageService
class in the constructor
method itself.
It can be done like this,
Filepath: /greet/greet.controller.ts
import { Controller, Get } from "@nestjs/common";
import { ImageService } from "../image/image.service";
@Controller("/greet")
export class GreetController {
// declaring and initializing the `ImageService` provider
// class using the fast and short way in the `constructor` method itself
constructor(private imageService: ImageService) {}
// The `Get()` decorator function will instruct the
// Nestjs runtime to use the `getImage()`
// method for a `GET` of `/greet` endpoint.
@Get()
getImage() {
// using the `getRandomImage()` method from the
// instance of the `ImageService` provider class.
return this.imageService.getRandomImage();
}
}
Now to tie everything up, we have to add the GreetModule
module class to the imports
array of the app root
module (app.module.ts
) which can be found at the root of the src
directory.
It can be done like this,
Filepath: /app.module.ts
import { Module } from "@nestjs/common";
import { GreetModule } from "./greet/greet.module";
@Module({
imports: [GreetModule], // <- add GreetModule here
})
export class AppModule {}
Now if you go to the /greet
API endpoint in the browser, you can see the image url as the response.
We have successfully integrated and used an external module provider
class method in another module's controller
in Nestjs. Yay 🥳!
See the above code live in codesandbox.
That's all 😃.