Tuesday, December 19, 2017

How to Inject and Use AngularJS Services in Angular

Angular developers looking to upgrade their codebase from AngularJS to Angular (v2+) will probably use a hybrid approach via the UpgradeModule and migrate their code over time. During this process you'll probably need to inject and re-use one of your existing AngularJS services in an Angular component or provider. You may also need an existing built in AngularJS service (i.e. $routeParams, $location, etc.). This isn't difficult to do, and the steps are below.

1. Upgrade the AngularJS service/provider to Angular

In your Angular app module, use an Angular factory provider that will request the service from the AngularJS $injector.

providers: [
  { provide: 'myAngularJsService', useFactory: ($injector: any) => $injector.get('myAngularJsService'), deps: ['$injector'] },
  { provide: '$routeParams', useFactory: ($injector: any) => $injector.get('$routeParams'), deps: ['$injector'] }
]

2. Inject the upgraded service in Angular

Using @Inject you will be able to inject your upgraded service for use in an Angular component or provider.

export class MyAngularComponent{

constructor(
  @Inject('myAngularJsService') private myAngularJsService,
  @Inject('$routeParams') private $routeParams
)

  //Implementation...
  myAngularJsService.doSomething();
}

3. Optionally create your own service factory

It's advisable to create a separate factory so it is easier to reference and then upon full migration of code easily delete as well. One note that can be the Achilles heel of this method - it requires the ability to be able to ES6 style import your external module. If your legacy AngularJS code is sill using internal modules and not external modules, this will not be possible as using an old style internal module reference in Angular will not work. So if your entire app is already using external modules you can set up your own factory as shown below.

import { MyAngularJsService} from './my-angularJs.service';

export function myAngularJsServiceFactory(i: any) {
  return i.get('myAngularJsService');
}

export const myAngularJsServiceProvider = {
  provide: MyAngularJsService,
  useFactory: myAngularJsServiceFactory,
  deps: ['$injector']
};

Now it can be registered in the app module via the exported provider created above.

import { myAngularJsServiceProvider } from './upgraded-providers';

//app module or module implementation...
providers: [myAngularJsServiceProvider]

In the Angular component or provider where injected, you can just import the service and use directly in the constructor.

import { MyAngularJsService} from './my-angularJs.service';

export class MyAngularComponent{

constructor(
  private myAngularJsService: MyAngularJsService
)

  //Implementation...
  myAngularJsService.doSomething();
}

The advantage of the above method is now upon injecting, you don't have to use the string handle and will get proper type checking.

3 comments:

  1. I am really enjoying reading your well written articles. It looks like you spend a lot of effort and time on your blog. I have bookmarked it and I am looking forward to reading new articles. Keep up the good work. Share more interesting posts regarding AngularJS.
    Why Should you use AngularJS

    ReplyDelete
  2. Very good read. Thank you for sharing. I am also a Developer. This is great and informative article. So thank you.

    ReplyDelete
  3. Thank you for your help. I'm looking for something like that

    ReplyDelete