Guides

Dependency Injection Demo

Image Empty Form

Launch Demo Application

Description

The Dependency Injection application exemplifies using a simple Angular template based Form that uses a data service to hold the submitted data. The data service provides a data stream to publish updates. A view component subscribes to the data stream and displays the most recent submitted user data in table format.

To display the User data table, enter values in the Form and click on the Create button.

Image User Data Entry

This will result in the data getting sent the data service which then broadcasts the new data. The data view component listens for updates from the data service and presents the most recent data in a table like the following.

Image Table View.

Application Structure

The Dependency Injection application is composed of 3 components and 1 service.

Components

  1. AppComponent
  2. FormNewUserComponent
  3. UserInfoComponet

Service

  • NewUserService

Architecture

The Angular application makes use of RxJS to create a data stream to publish the user data. When the Create button is clicked, the user data is sent to the service using an API call. The service then publishes the data using an RxJS Subject.

Image App UML

The HTML Form is provided by component FormNewUserComponent. The table view of the user info is handled by UserInfoComponent. It simply subscribes to the Subject publishing the user data.

Opening Augury

To use Augury, we must open DevTools first with the following keyboard shortcut.

Ctrl + Shift + I (Cmd + Opt + I on Mac)

When DevTools opens, select the Augury tab located on the far right. In DevTools, under the Component Tree tab, you will see the following parent and children tree relationship for Angular components and any HTML DOM elements.

Image Component Tree

The default view setting, called the Hybrid view, can be changed from the settings.

Image Component Tree View Settings

Component View

Augury shows that the Dependency Injection Angular application has 3 components. The Root component is called AppComponent which in turn contains 2 child components, UserInfoComponent and FormNewUserComponent.

Select AppComponent from the Component Tree, on the right side in the Properties tab, we see the single property title under State. Augury allows the value of property title to be modified. This is indicated by displaying an edit field with a dashed blue line on the bottom.

Image App Title Property

Feel free to change the value and press the Enter key to see the change get reflected in the Web page.

Viewing Source Code

In the Properties tab, next to the name of the component you will notice a clickable link called (View Source). By clicking on it, DevTools will switch to the Sources tab to show the TypeScript code of the selected component.

Image DevTool Sources.

In the TypeScript code, you see title property assignment, which is what is displayed in Augury's Properties tab.

 title = 'Angular Form: New User';

To return to Augury, click on the Augury tab.

Dependency

Let us take a look at the UserInfoComponent, select it from the Component Tree. In the Properties tab, we see that under State, the component has only one property newUserService and one dependency to NewUserService.

Image User Info Component

If we take a look at the source code, the class for the component actually has 2 members (properties), userInfo and newUserService.

export class UserInfoComponent {

  userInfo;

  constructor( private newUserService: NewUserService ) {
    this.newUserService.getStream().subscribe(
      data => this.userInfo = data
    );
  }

}

Since property userInfo is not assigned a value, TypeScript removes it during compile, this is why the property is not seen in the Properties tab. Likewise newUserService is assigned a value (a reference to the service) by the Injector using Angular's Dependency Injection (DI).

Let us publish a hand crafted user info using Augury. In the Properties tab, under State expand property newUserService as shown below so the Emit button is visible.

Type in a JavaScript object with the fields, name, email and password containing some value.

Image User Info Emit

When this data has been emitted, you will see this data displayed by the UserInfoComponent in a table.

Image User Info Emit Table

In the Properties tab, the State should now look like this.

Image Emitted User Info Properties

Since the surname field was left out from the emitted user info data, it shows up empty in the table on the Web page. Likewise it's missing under State for object userInfo.

Injector Graph

Besides looking at the source code to determine dependencies, Augury provides a visual way to see this through the Injector Graph tab located next to the Properties tab. If we select it, we will see a dependency tree.

Image User Info Injector Graph

For this new information to be useful, you need to understand how the Injector graph is generated. It does not show the graph for the entire application. What gets shown is the dependency of the selected component and its ancestry chain to the Root injector.

Further reading material of the Injector Dependency Tree can be found in the Angular guide.

Understanding The Graph

Let us look at how to read the Injector graph. At the top we have the Root injector, which is found in the NgModule at the root of the application.

In the code, looking at file app.module.ts we see 3 components being declared by the root module as well as the one service NewUserService that is registered with the Root injector.

@NgModule({
  declarations: [
    AppComponent,
    FormNewUserComponent,
    UserInfoComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [NewUserService ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Looking at the graph, we see that UserInfoComponent is projected by AppComponent, the parent component. This is obvious if we look at the code (app.component.ts), in the template string we see <app-user-info> being used.

@Component({
  selector: 'app-root',
  template: `
...
    <div class="pt3">
      <app-user-info></app-user-info>
    </div>
...
`
})
export class AppComponent {
  title = 'Angular Form: New User';
}

Looking next at UserInfoComponent, we see a red line extending to the right, connecting to a circle labeled NewUserService. This denotes that service NewUserService is being injected into component UserInfoComponent.

The dashed blue line from the Root injector to NewUserService indicates this service is provided by the Root injector. This identifies the service as being a singleton (a global shared instance), that is available throughout the entire application.

Colours

Pay close attention to the colours of the components and service. For example, the circle is hollow for service. This means the service is not provided by the component, instead it is being provided from an ancestor in the dependency tree.

Parent Level Injector

Let us play around with service registration. Instead of the service being provided by the Root injector, we are going to override this behaviour. Let us have AppComponent register the service being used by UserInfoComponent. Open the file app.component.ts and add a providers array and import like this:

import { NewUserService  } from './new-user.service';

@Component({
  providers: [NewUserService ],
  selector: 'app-root',
  ...

Now the Injector graph looks like this:

Image User Info Injector Graph

The only thing that has changed is the dashed blue line, coming from AppComponent to the service. This as we should know now, indicates NewUserService is coming from the parent injector of AppComponent.

Component Level Injector

A service can also be injected at the component level. To see how this would look from the Injector Graph, we can make a simple code alteration to UserInfoComponent in the file user-info.component.ts.

In the @Component decorator, include the providers array like this:

@Component({
  providers: [NewUserService ],
  selector: 'app-user-info',
  template: `
  ...
})

If we now look at the Injector Graph, we will see the dashed line has disappeared.

Image User Info Injector Graph

The NewUserService is being injected into UserInfoComponent as well as being registered with UserInfoComponent. Pay attention to the ball in the graph for the service, it has now become filled.

Note: These changes will break the code as the application no longer uses the same singleton service to communicate data. This was for demonstration purpose only for the Injector Graph.