Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I inject an AngularJS service in an Angular 5 component?

I'm migrating an AngularJS project to Angular 5 using ngUpgrade but I'm running into a problem when trying to inject an AngularJS service in one of my new components.

I followed Angular's upgrade guide and created a serviceProvider that uses the $injector (see code below) but I keep getting this error:

core.js:1449 ERROR Error: Uncaught (in promise): Error: Trying to get the AngularJS injector before it being set.

I suspect I need to use forwardRef somewhere to fix this, but I'm unable to find out how and where (and why).


Following the example of the upgrade guide I created a serviceProvider as follows:

ajs-upgraded-providers.ts:

// The AngularJS service I want to use
import { AuthenticationService } from '../ajs/services/authentication.service';

export function authenticationServiceFactory($injector) {
    return $injector.get('authentication');
}

export const authenticationServiceProvider = {
    provide: AuthenticationService,
    useFactory: authenticationServiceFactory,
    deps: ['$injector']
};

Then I provide that to the app's NgModule:

app.module.ts:

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        UpgradeModule,
    ],
    providers: [
        authenticationServiceProvider,
    ],
    bootstrap: [
        AppComponent,
    ],
})
export class AppModule {
}

I bootstrap that module using ngUpgrade:

main.ts

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { UpgradeModule } from '@angular/upgrade/static';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

// Import our AngularJS module
import '../ajs/app';

platformBrowserDynamic()
    .bootstrapModule(AppModule)
    .then(platformRef => {
        // Use the upgrade module to bootstrap the hybrid
        const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
        upgrade.bootstrap(document.documentElement, ['myAngularJSApp']);
    });

If I understand correctly, this should allow me to directly inject the AngularJS service into my component like so:

login.component.ts

import { Component } from '@angular/core';

import { AuthenticationService } from '../ajs/services/authentication.service';

@Component({
    selector: 'my-login-page',
    templateUrl: './login-page.component.html'
})
export class LoginPageComponent {    
    constructor(private authenticationService: AuthenticationService) {
        console.log('authentication', authenticationService);
    }
}

Can I do anything to simplify this even more? I tried to follow the upgrade guide as closely as possible, so why doesn't this work?

like image 487
Stephan Muller Avatar asked May 17 '18 13:05

Stephan Muller


1 Answers

You need to add

providers: [AuthenticationService] 

in Component declaration, like this:

import { Component } from '@angular/core';

import { AuthenticationService } from '../ajs/services/authentication.service';
@Component({
    selector: 'my-login-page',
    templateUrl: './login-page.component.html',
    providers: [AuthenticationService] 
})
export class LoginPageComponent {    
    constructor(private authenticationService: AuthenticationService) {
        console.log('authentication', authenticationService);
    }
}
like image 96
Nickolay Poliakow Avatar answered Sep 16 '22 19:09

Nickolay Poliakow