Steve D
Steve D

Reputation: 627

Angular package using its own service inside component

I'm creating an angular library for components shared across multiple apps. I'm running into trouble when using a service from inside the library inside a component from the library.

The service is intended to be injected at the root of the app (not library) and can be used throughout the app.

In this scenario, we're looking at the ToastService and UIToastComponent. The UIToastComponent is exported from the UIToastModule.

The app then imports the UIToastModule inside the application's AppModule, where is also provides the ToastService.

The <ui-toast></ui-toast> tag sits in the application's app.component.html file.

The idea being, in any component inside the application, the developer can inject ToastService and call this.toastService.success('Great Success!'), which is picked up by the UIToastComponent and displays the toast.

The constructor for the UIToastComponent can't seem to pick up the service, and at runtime I the following error:

Uncaught ReferenceError: ToastService is not defined
at UIToastComponent.ctorParameters (ngx-example-library.js:197)
at ReflectionCapabilities._ownParameters (core.js:2060)
at ReflectionCapabilities.parameters (core.js:2095)
at JitReflector.parameters (platform-browser-dynamic.js:61)
at CompileMetadataResolver._getDependenciesMetadata (compiler.js:15635)
at CompileMetadataResolver._getTypeMetadata (compiler.js:15527)
at CompileMetadataResolver.getNonNormalizedDirectiveMetadata 
(compiler.js:15012)
at CompileMetadataResolver.loadDirectiveMetadata (compiler.js:14866)
at eval (compiler.js:34392)
at Array.forEach (<anonymous>)

The import statement for the ToastService inside the UIToastComponent looks like this:

import { ToastService } from '../../services/toast.service';

The library follows the Angular Package Format v5 and was originally based on https://github.com/juristr/ngx-tabs-libdemo

Here's the sourcecode for the library: ngx-example-library

EDIT

I've implemented forRoot() as per Günter Zöchbauer's suggestion but unfortunately still I get the same result, its likely I've implemented it incorrectly...

Here's what the newly created UICoreModule looks like inside the library:

import { ModuleWithProviders, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { UIToastComponent } from './components/toast/toast.component';
import { ToastService } from './services/toast.service';

@NgModule({
    declarations: [
        UIToastComponent,
    ],
    providers: [],
    imports: [
        CommonModule,
    ],
    exports: [
        UIToastComponent,
    ]
})

export class UICoreModule {

    public static forRoot(): ModuleWithProviders {
        return {ngModule: UICoreModule, providers: [ToastService]};
    }

}

And here's the AppModule inside the application:

import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';

import {AppComponent} from './app.component';
import {UICoreModule} from 'ngx-example-library';

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        UICoreModule.forRoot()
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule {
}

Appreciate the help with this one, it's a real mind-boggler this one. Bet it's really easy - when you know how!

EDIT (2)

The solution mentioned above does work in AOT mode, but not JIT mode. Happy to live with that for now, the app builds AOT anyway. Development may become when app grows though.

Upvotes: 2

Views: 1725

Answers (1)

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657731

You need to implement forRoot in the module that defines your package, provide the service there and import the module in AppModule with MyModule.forRoot()

See also https://angular.io/guide/ngmodule-faq#what-is-the-forroot-method

Upvotes: 2

Related Questions