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:
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