AngularJS services are substitutable objects that are wired together using dependency injection (DI). You can use services to organize and share code across your app.

AngularJS services are:

Lazily instantiated – AngularJS only instantiates a service when an application component depends on it.

Singletons – Each component dependent on a service gets a reference to the single instance generated by the service factory.

AngularJS offers several useful services (like $http), but for most applications you’ll also want to create your own.

Logging Service

Example can be logging service. Create file app/logging.service.ts:

export class LoggingService {
  logStatusChange(status: string) {
    console.log("A server status change, new status: " + status);
  }
}



app/account/account.component.ts

Important parts are :

providers: [LoggingService]
constructor(private loggingService: LoggingService) {}

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

@Component({
  selector: 'app-new-account',
  templateUrl: './new-account.component.html',
  styleUrls: ['./new-account.component.css'],
  providers: [LoggingService]
})
export class NewAccountComponent {
  @Output() accountAdded = new EventEmitter<{name: string, status: string}>();

  constructor(private loggingService: LoggingService) {

  }

  onCreateAccount(accountName: string, accountStatus: string) {
    this.accountAdded.emit({
      name: accountName,
      status: accountStatus
    });
    this.loggingService.logStatusChange("HELLO");
  }
}



Data Service

We can store data in a service, for example array of accounts.
app/accounts.service.ts

export class AccountsService {
    accounts = [
      {
        name: 'Master Account',
        status: 'active'
      },
      {
          name: 'Testaccount',
          status: 'inactive'
      },
      {
          name: 'Hidden Account',
          status: 'unknown'
      }
    ];

  addAccount(name: string, status:string) {
    this.accounts.push({name:name, status: status});

  }

  updateStatus(id: number, status:string) {
    this.accounts[id].status = status;

  }
}



app/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'],
  providers: [AccountsService]
})
export class AppComponent {
  accounts: { name: string, status: string}[] = [];

  constructor( private accountsService: AccountsService) {

  }

  ngOnInit() {
    this.accounts = this.accountsService.accounts;
  }
}



!IMPORTANT In this file AccountsService isnt in providers. Thats because when you put service into providers, you are creating new instance. And we want to use instance which was created in app.component.ts, the same array of accounts.

new-account.components.ts

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

@Component({
  selector: 'app-new-account',
  templateUrl: './new-account.component.html',
  styleUrls: ['./new-account.component.css'],
  providers: [LoggingService]
})
export class NewAccountComponent {
  

  constructor(private loggingService: LoggingService,
          private accountsService: AccountsService) {

  }

  onCreateAccount(accountName: string, accountStatus: string) {
    this.accountsService.addAccount(accountName,accountStatus);
    this.loggingService.logStatusChange("HELLO");
  }
}

Service in app.module.ts

There is providers also in app.module.ts. Put your services here if you want to have it available in whole app.



Injecting Service in Service

If we want to use Service inside another Service. We need firt to import it, make constructor and use @Injectable.

accounts.service.ts

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

export class AccountsService {
    accounts = [
      {
        name: 'Master Account',
        status: 'active'
      },
      {
          name: 'Testaccount',
          status: 'inactive'
      },
      {
          name: 'Hidden Account',
          status: 'unknown'
      }
    ];
  
  constructor(private loggingService: LoggingService) {}

  addAccount(name: string, status:string) {
    this.accounts.push({name:name, status: status});
    this.loggingService.logStatusChange(status);
  }


  updateStatus(id: number, status:string) {
    this.accounts[id].status = status;

  }
}



Cross-Component Communication

accounts.service.ts

 statusUpdated = new EventEmitter<string>();



account.component.ts

this.accountService.statusUpdated.emit(status);



new-account.component.ts

this.accountService.statusUpdated.subscribe(
  (status:string) => alert("new Status: "+ status);
);