Check out our Angular Book Series.

Do You Need Injectable Metadata? - Dependency Injection and Angular - Part 3

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, and part 2 where we remove the providedIn configuration object.

Do you need the Injectable Metadata?

It is a little known fact about Angular services that you do not need the injectable metadata at all to make things work. First, generate a new service:


ng generate service services/service3

Open it up:


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

You've seen this in our previous samples. Now remove the injectable metadata completely and add a shared value into the service:


import { Injectable } from '@angular/core';
export class Service3Service {
myValue = 'default 3';
constructor() { }
}

This will still work as an Angular service, even without the appropriate metadata. The trick is that you need to add it to the app.module.ts file. Find the providers array as part of the NgModule metadata and add it:


providers: [
Service2Service,
Service3Service
],

Be sure to import the service:


import {Service3Service} from './services/service3.service';

Now, we can mirror our previous samples using service3. Switch over to view1.component.ts and inject Service3Service into the component:


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

You'll have to import the Service3Service here:


import {Service3Service} from './services/service3.service';

In view1.component.html, add a bindable input to the service3 value:


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

Go over to view2.component.ts to inject service3:


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

Add the service3 import:


import {Service3Service} from './services/service3.service';

And output the value:


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

Now rerun the app:

You should see everything working as expected. Type in the service 3 input of view 1 and the service 3 output in view 2 should output.

What's Next

You can play with the code here.

In the next article of this series, I'm going to show you how to set up providers for a specific component, instead of for the full application.

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.