Reputation: 11250
I am trying to create an Angular Library to share code, within a NX workspace. I have created the library, and a component works, but I cannot get a custom pipe to work.
My simple example is to have a Pipe shared from the library. In our code, we store a date and time in specific formats. The custom pipes work to then convert the specific format into a proper Date object, then the Angular DatePipe is called to transform the data.
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FlexLayoutModule } from '@angular/flex-layout';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MyDatePipe } from './my-date.pipe';
import { MyTimePipe } from './my-time.pipe';
import { LoadingComponent } from './loading/loading.component';
@NgModule({
imports: [
CommonModule,
FlexLayoutModule,
MatProgressSpinnerModule
],
declarations: [MyDatePipe, MyTimePipe, LoadingComponent],
exports: [LoadingComponent, MyDatePipe, MyTimePipe],
})
export class AngularUiModule {}
I have a module to export the shared code I am using. In the above example, the LoadingComponent is exported, and I use it in the same component I am trying to use the MyDatePipe in. In my AlertModule, which is showing the data, I can import the LoadingComponent, but not the MyDatePipe.
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AlertsRoutingModule } from './alerts-routing.module';
import { AlertListComponent } from './components/alert-list/alert-list.component';
import { AlertDetailComponent } from './components/alert-detail/alert-detail.component';
import { AlertLineComponent } from './components/alert-line/alert-line.component';
import { AlertsService } from './alerts.service';
import { AngularUiModule } from '@chowarmaan/angular-ui';
@NgModule({
declarations: [
AlertListComponent,
AlertDetailComponent,
AlertLineComponent,
],
imports: [CommonModule, AlertsRoutingModule, AngularUiModule],
providers: [AlertsService, MyDatePipe],
})
export class AlertsModule {}
When I try to reference the MyDatePipe in the providers, I get a Module '"@chowarmaan/angular-ui"' has no exported member 'SlsDatePipe'.ts(2305)
.
If I then directly export the SlsDatePipe in the library index.ts file:
export * from './lib/angular-ui.module';
export * from './lib/my-date.pipe';
export * from './lib/my-time.pipe';
I can then import the MyDatePipe in the module. With the import, I can then add it to the providers array. However, my code will now fail on the browser as there is no provider for the DatePipe from Angular.
The browser error when I do not include the DatePipe in the providers array:
alert-list.component.html:3 ERROR NullInjectorError: R3InjectorError(AlertsModule)\[DatePipe -\> DatePipe -\> DatePipe -\> DatePipe\]:
NullInjectorError: No provider for DatePipe!
at NullInjector.get (core.mjs:6367:27)
at R3Injector.get (core.mjs:6794:33)
at R3Injector.get (core.mjs:6794:33)
at R3Injector.get (core.mjs:6794:33)
at R3Injector.get (core.mjs:6794:33)
at ChainedInjector.get (core.mjs:13824:36)
at lookupTokenUsingModuleInjector (core.mjs:3293:39)
at getOrCreateInjectable (core.mjs:3338:12)
at Module.ɵɵdirectiveInject (core.mjs:10879:12)
at MyDatePipe_Factory (my-date.pipe.ts:11:25)
I have to import the DatePipe into the module as well. This seems to be incorrect to me, as the DatePipe is in the MyDatePipe code, and how would others know this is being used? I would not expect to have to import everything I need in all modules using my library.
I expect I am doing something wrong in the library definition.
import { DatePipe } from '@angular/common';
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'my_Date'
})
export class MyDatePipe implements PipeTransform {
constructor(private AngularDatePipe_: DatePipe) {}
public transform(DateValue: string, OutputFormat: string): unknown {
if (DateValue === null || DateValue === undefined) {
return null;
}
...
return this.AngularDatePipe_.transform(DateObject, OutputFormat);
}
However, if I do add the DatePipe as well to the module's Providers array, then the pipe does work as epected. Adding both the providers array works, and the pipe works on my component, but I would have thought the DatePipe would have not been needed if set properly in my library.
providers: [AlertsService, SlsDatePipe, DatePipe],
Upvotes: 1
Views: 760
Reputation: 597
I hope this helps. I've got an NX angular micro frontend setup. We've got a couple apps and a bunch of libraries:
-- apps
-- app1
-- app2
-- host
-- libs
-- app1
-- app2
-- shared
-- utils
-- customPipesModule
-- ui
A component inside libs/shared/ui
requires a pipe from customPipesModule
. I kept getting errors about not finding the pipe or a vague ecmp
error.
Per angular, customPipesModule
declares and exports my pipes and libs/shared/ui-lib
imports customPipesModule
. This worked fine in our non-nx repo but not NX.
To fix the issue in the new NX repo, I had to make sure that libs/shared/utils
index.ts
file exported the customPipesModule
as well as ALL the pipes. I was then able to use a pipe inside the component in libs/shared/ui
.
Upvotes: 0