Angular 2 – Using services and dependency injection

Injecting a custom service into components

  • A Service is created when we need a centralized component which serves some functionality to multiple components. Also we would expect to be a singleton instance.

app.component.html

      <button type="button" (click)="testLoggingService('one')" name="button">Test Logging Service One</button>
      <button type="button" (click)="testLoggingService('two')" name="button">Test Logging Service Two</button>

app.component.ts

import { Component } from '@angular/core';
import { LoggingService } from './logging.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  providers: [LoggingService]
})
export class AppComponent {
  myCondition = true;
  value=10;

  constructor(private LoggingService: LoggingService){}
  testLoggingService(msg) {
    this.LoggingService.logStatusChange(msg);
  }
}

logging.service.ts

export class LoggingService {
  logStatusChange(status: string) {
    console.log('A server JAJAJA JIJIJIJ JOJOJOJ' + status);
  }
}

Angular has a Hierarchical Injector for dependencies:

Captura de pantalla 2017-04-28 a las 11.41.31

WARNING: If we declare in [providers] a service in a child component which is declared in the parent component, we are overwritting the parent one , so they are two different instances.

For using a service declared in the parent component we still need to define it as a parameter in the constructor but we don’t need to declare it in the [providers] decorator.

The highest level to declare a dependency is in the AppModule.

Injecting Services into Services

  • We inject both services into AppModule.

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';
import { BasicHighlightDirective } from './basic-highlight.directive';
import { BetterHighlightDirective } from './better-highlight.directive';
import { UnlessDirective } from './unless.directive';
import { AccountsService } from './accounts.service';
import { LoggingService } from './logging.service';

@NgModule({
  declarations: [
    AppComponent,
    BasicHighlightDirective,
    BetterHighlightDirective,
    UnlessDirective
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [AccountsService, LoggingService],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.html

      <button type="button" (click)="addAccount()" name="button">Add Account</button>
      <button type="button" (click)="removeAccount()" name="button">Remove Account</button>
      <ul>
       <li *ngFor="let account of accounts">Account #{{account.id}}</li>
      </ul>

app.component.ts

import { Component } from '@angular/core';
import { AccountsService } from './accounts.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  myCondition = true;
  value=10;
  accounts = this.AccountsService.accounts;

  constructor(private AccountsService: AccountsService){}
  addAccount() {
    this.AccountsService.addAccount();
  }
  removeAccount() {
    this.AccountsService.removeAccount();
  }
}

accounts.service.ts

import { Injectable } from '@angular/core';
import { LoggingService } from './logging.service';

@Injectable()
export class AccountsService {
  accounts = [];

  constructor(private logginService: LoggingService){}

  addAccount() {
    const newId = this.accounts.length;
    this.accounts.push({
      date: new Date().getTime(),
      id: newId
    });
    this.logginService.log('Account #' + newId + ' added!');
  }

  removeAccount() {
    this.accounts.splice(this.accounts.length-1,1);
    this.logginService.log('Account removed!');
  }
}

Cross Components Communication using services

accounts.service.ts

...
  sendMessage = new EventEmitter<string>();
...

component-one.component.ts

...
  constructor(private accountsService: AccountsService) { }
...

  emitEvent() {
    this.accountsService.sendMessage.emit('Hola caracola!!');
  }

component-one.component.html

<p>
  <button type="button" (click)="emitEvent()" name="button">Component One emits event to Component Two</button>
</p>

component-two.component.ts

import { Component, OnInit } from '@angular/core';
import { AccountsService } from '../accounts.service';

@Component({
  selector: 'app-component-two',
  templateUrl: './component-two.component.html',
  styleUrls: ['./component-two.component.css']
})
export class ComponentTwoComponent implements OnInit {

  receivedMsg:string = 'No message received yet';

  constructor(private accountsService: AccountsService) {
    this.accountsService.sendMessage.subscribe(
      (message: string) => {
        this.receivedMsg = message;
      }
    );
  }

  ngOnInit() {
  }

}

component-two.component.html

<p>
  Component Two receives event --> Message:{{receivedMsg}}
</p>

ds

dsd

sd

sd

sd

sd

sds

f