Check out our Angular Book Series.

providedIn - Dependency Injection and Angular - Part 2

I was chatting with a colleague recently, and he had some confusion about how dependency injection works with Angular. There are a bunch of ways to set up Dependency Injection with Angular, but as always the documentation seems lacking. I'm writing this series of posts to discuss the ways and to explain what works and what won't work.

Check out the first post where we set up a project and created a default Angular Service.

This post will expand on the previous sample, and examine the providedIn configuration object to the Injectable metadata a bit more deeply.

Remove the providedIn as part of injectable metadata

Let's generate another service:


ng generate service services/service2

You'll see something like this:

Open up the file:


import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class Service2Service {
constructor() { }
}

We're going to add a property to this service to be shared:


myValue = 'default 2';

This is just like the last one. We're also going to change the Injectable metadata to remove the configuration object. Before the class definition, you should see:


@Injectable()

Now try to inject the provider into view1.component.ts . If you're building off the previous sample, you'll see this:


constructor(public service1: Service1Service, public service2: Service2Service) { }

Be sure to import Service2Service into the component:


import {Service2Service} from '../services/service2.service';

Rerun the app. It doesn't load. Look at the debugger console:

You see a lot of injector errors. Even though we created Service2Service with injectable metadata, Angular does not know how to find it. That is because we never told Angular how to find it. One way to do that is to set the providedIn object as we did in the previous sample. But we removed that metadata and such the error.

The alternative is to tell the Angular module to make this class available as an injectable service. We do this using the providers array on the NgModule annotation. Open up app.module.ts and add a providers array:


providers: [
Service2Service
],

Be sure to import the class here too:


import {Service2Service} from './services/service2.service';

Now re-run the app and you should get no errors. Unfortunately, we aren't do anything with service 2 yet. Let's mirror the sample we used for service 1. First, in view1.component.html, add an input that binds to service2:


<h1>View 1: Service 2</h1>
<input [(ngModel)]="service2.myValue">

Next, inject service2 into the constructor of view2.component.ts:


constructor(public service1: Service1Service, public service2: Service2Service) { }

Import Service2Service:


import {Service2Service} from '../services/service2.service';

Then update view2.component.html:


<h1>View 2: Service 2</h1>
{{service2.myValue}}

Now rerun the app:

As you type in the service 2 input of view 1; you should see the service 2 output from view 2 update. It works perfectly.

What's Next

You can play with the code here.

In the next article of this series, I'm going to remove the injectable metadata completely and see how that works.

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
Comments are not allowed for this entry.
All Content Copyright 2005, 2006, 2007, 2008, 2009 Jeffry Houser. May not be reused without permission
BlogCFC was created by Raymond Camden. This blog is running version 5.9.2.002.