Check out our Angular Book Series.

Can I create a Provider in Angular without listing it in the provider array?

This was something new I just discovered. You can create an Angular provider, as a singleton and do not have to list it in the provider array. This post will show you how.

The setup

To set up this project, I used the Angular CLI to create a new project. Then I created two services: ServiceOneService and ServiceTwoService. I also created two views: view1 and views2. You can find the code behind this project in this blog's GitHub repo.

Modify the main app.component.html template to include the two views:


<app-view1></app-view1>
<br/>
<app-view1></app-view1>

Create the services

Service1 should look something like this:


import { Injectable } from '@angular/core';
@Injectable()
export class ServiceOneService {
text = `from service one`;
constructor() { }
}

It is created as injectable, and has a single property. Open the app.module add this as a provider:


providers: [
ServiceOneService
],

Service2 should look something like this:


import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class ServiceTwoService {
text = `from service two`;
constructor() { }
}

The service looks almost identical, even having the same text property on it. The big difference is in the injectable metadata, we added a providedIn: 'root'. This is the trick to creating a provider without defining it as a provider. means that the first time the service is injected, Angular will create the Singleton just as if it were set up as an explicit provider.

The Views

Open up the TypeScript file for view1 and view2 and load the services:


constructor(public service1: ServiceOneService, public service2: ServiceTwoService) { }

Open up the HTML component for each view and paste this in there:


From Service 1, set up as traditional provider:
<input type="text" [(ngModel)]="service1.text" >
<Br/><Br/>
From Service 2, using providedIn = root:
<input type="text" [(ngModel)]="service2.text">

This just puts an input on the screen, one binding to the service1.text, and the other binding to service2.text.

Since we're using ngModel don't forget to load the import the FormsModule into the appModule:


imports: [
BrowserModule,
FormsModule
],

Run the Code

Now run the code and load it in a browser. When you type in the service 1 input in one component, the input in the other component should also change:

This is what is normal and we're used to because we set up Service1 as a provider and the single instance should be shared between the two components.

Now try to type in the service 2 input. The values also change:

This surprised me, since Service2 is not set up as a provider. However, the `providedIn` metadata tells Angular to create Service2 as a service. It works like magic.

Get The Full Source for this Sample.

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
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.