How to declare a pipe globally to use in different modules?

85,324

Solution 1

In Angular a good technique for sharing common directives, components, pipes, etc. is to use a so called shared module.

Those modules declare and export common parts, to make them usable for any of your other modules.

The fundamentals section of the angular documentation is a very good read about shared modules.

Let's take as example your currConvert pipe.

  • Declare new NgModule called ApplicationPipesModule

  • Add the pipe to the declarations and exports arrays of the NgModule-decorator metadata

  • Add any modules that may be required for your pipe to work to the imports array

    // application-pipes.module.ts
    // other imports
    import { CurrConvertPipe } from './{your-path}';
    
    @NgModule({
      imports: [
        // dep modules
      ],
      declarations: [ 
        CurrConvertPipe
      ],
      exports: [
        CurrConvertPipe
      ]
    })
    export class ApplicationPipesModule {}
    
  • import the created ApplicationPipesModule module into the modules where your pipe is going to be used, by adding it to the imports array

    // my-module1.module.ts
    // other imports
    import { ApplicationPipesModule } from './{your-path}';   
    
    @NgModule({
     imports: [
       // other dep modules
       ApplicationPipesModule
     ],
     declarations: [],
     exports: []
    })
    export class MyModule1 {}
    

Solution 2

you can use Sharing Modules for share your service, directive, pipes, components

you have to create an module and import the pipes ,directive, services or components and set the declaration, export and providers for the services.

import the sharing module in to where ever you want and use it.

basically pipes and directives declared and exported in NgModules meta data. for services define forRoot which returns the providers to access other modules.

  • shareModule.ts

    
    import { NgModule, ModuleWithProviders } from '@angular/core';
    import { appDirective } from './{your-path}';
    import { appPipe } from './{your-path}';
    import { appService } from './{your-path}';
    
    @NgModule({
      declarations: [
        appPipe,
        appDirective
      ],
      exports: [
        appPipe,
        appDirective
      ]
    })
    export class SharingModule {
      static forRoot(): ModuleWithProviders {
        return {
          ngModule: SharingModule,
          providers: [ appService ]
        };
      }
    }
    
  • my-module1.module.ts

    
    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    
    import { myComponent } from './{your-path}';
    
    import { SharingModule } from './{your-path}';
    
    @NgModule({
      declarations: [
        myComponent
      ],
      imports: [
        BrowserModule,
        SharingModule.forRoot()  
      ],
    })
    export class AppModule {}
    

Like wise you can do in othe moduls also.

Solution 3

You should make a module, i.e. SharedModule and declare your pipe there. Then you should export pipe in SharedModule and import your SharedModule in both Module1 and Module2. There's a great article in Angular's docs: https://angular.io/docs/ts/latest/guide/ngmodule.html#!#shared-module

Solution 4

Consider you have this structure:

app 
 -shared
   -components
     -DateComponentModule.ts
   -pipes
     -DatesPipe
     -DatesPipeModule.ts

 -SharedModule.ts  

When you are using DatesPipeModule in DateComponentModule.

  1. Declare and Export DatesPipe in DatesPipeModule

  2. Now Import DatesPipeModule directly into DateComponentModule.

DatesPipeModule.ts

import { DatesPipe} from './{your-path}';

@NgModule({
  imports: [],
  declarations: [ 
    DatesPipe
  ],
  exports: [
    DatesPipe
  ]
})
export class DatesPipeModule{}

DateComponentModule.ts

import { DatesPipeModule} from './{your-path}';

@NgModule({
  imports: [DatesPipeModule],
  declarations: [],
  exports: []
})
export class DatesPipeModule{}

You can also export it from SharedModule and import it in DatesComponentModule.ts, but SharedModule will not load before pipes, so it throws an error.

Solution 5

If you generate a pipe using CLI for a shared module you will need to add the pipe to the 'exports' list manually. My pipe error'd in the browser until I added the pipe as an export in my shared module I imported/declared it in.

Share:
85,324
Sajeetharan
Author by

Sajeetharan

👋 Follow and say Hi @Kokkisajee . Click here To know more about me

Updated on August 09, 2020

Comments

  • Sajeetharan
    Sajeetharan over 3 years

    I have a custom pipe named CurrConvertPipe

    import {Pipe, PipeTransform} from '@angular/core';
    import {LocalStorageService} from './local-storage';
    @Pipe({name: 'currConvert', pure: false})
    export class CurrConvertPipe implements PipeTransform {
      constructor(private currencyStorage: LocalStorageService) {}
    
      transform(value: number): number {
         let inputRate = this.currencyStorage.getCurrencyRate('EUR');
        let outputputRate = this.currencyStorage.getCurrencyRate(localStorage.getItem('currency'));
        return value / inputRate * outputputRate;
      }
    }
    

    I need to use this in two different modules, Module1 and Module2.
    When I import in Module1 and Module2, I get an error saying it should be declared in a higher level module.

    So I declare the pipe inside the app.module.ts

    import './rxjs-extensions';
    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import { FormsModule } from '@angular/forms';
    import { AppRoutingModule } from './app-routing.module';
    import { AppComponent } from './app.component';
    import { CurrConvertPipe } from './services/currency/currency-pipe';
    @NgModule({
        imports: [
            BrowserModule,
            FormsModule,
            HttpModule,
            AppRoutingModule,
            Module1,         
            Module2
    
        ],
    
        declarations: [
            AppComponent,
            CurrConvertPipe
        ],
        providers: [
    
        ],
        bootstrap: [AppComponent]
    })
    export class AppModule { }
    

    But when I use it in Module1, it throws an error

    The pipe 'currConvert' could not be found

  • Ledzz
    Ledzz about 7 years
    @Sajeetharan app.module imports Module1 and Module2, so pipe is not imported in these modules. If you import SharedModule in Module1 then pipe gets imported in SharedModule and exports to Module1
  • Edoardoo
    Edoardoo over 5 years
    Not that it's your fault, but didn't work for me. I still get the Template parse errors. I've been debugging this thing for an hour, which is 55 minutes more than what it should take to set up a custom pipe. A very frustrating experience.
  • Maneesh Rao
    Maneesh Rao about 5 years
    I have done same thing but I am getting error: "application-pipes.module.ts module not found"
  • Buddybear
    Buddybear about 5 years
    Same concept can be used for reusing directives/components/services (except for service we need additional configuration). Nice explanation
  • Eddy Howard
    Eddy Howard almost 5 years
    Works perfect! Don't forget to add the NgModule import into the shared module. import { NgModule } from '../../../../node_modules/@angular/core';
  • eCommerce Guru
    eCommerce Guru about 4 years
    I needed to add my shared module to both the app module imports and my page-level module imports. I don't know why. I hate that I had to flail around until I stumbled on this solution.
  • Wildhammer
    Wildhammer almost 4 years
    Wouldn't this approach cause multiple instances of a service?
  • Wildhammer
    Wildhammer almost 4 years
    The pipe has service dependency, how would you deal with that?
  • Ledzz
    Ledzz almost 4 years
    @Wildhammer think that service must come in same module with pipe
  • Wildhammer
    Wildhammer almost 4 years
    Then you'd have multiple instances of that service per import. That is usually not okay.
  • juanbits
    juanbits over 3 years
    ohh i see the problem that you said: but SharedModule will not load before pipes, so it throws an error. thanks. I declared in the non shared module the pipe only for this module
  • Liam
    Liam almost 2 years
    ModuleWithProviders without a generic is now deprecated. That code should now be static forRoot(): ModuleWithProviders<SharingModule> {