Angular Services & Dependency Injection
Services reusable logic மற்றும் state-ஐ components-இலிருந்து வெளியே hold செய்கின்றன.
Services & DI Essentials
- What: ஒரு service reusable logic/state hold செய்கிறது. DI (dependency injection) தேவைப்படும் இடங்களில் instances supply செய்கிறது.
- Scope: Shared singleton-க்கு root-ல் provide செய்யவும், அல்லது isolated instances-க்கு component-ல் provide செய்யவும்.
- Use cases: Data fetching, caching, business rules, cross-component state.
- Mental model: DI power outlet போன்றது: நீங்கள் plug in செய்கிறீர்கள் மற்றும் Angular உங்களுக்கு ready instance தருகிறது.
- Decorator: மற்ற services inject செய்யும் classes-ல் @Injectable() பயன்படுத்தவும்.
Service Definition Example
import { Injectable } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class CounterService { value = 0; inc() { this.value++; } }
// Inject in a component
// constructor(public counter: CounterService) {}
Notes
- Related: Services consume செய்ய Components, services பயன்படுத்தும் Router for guards, மற்றும் data fetch செய்யும் HTTP services ஆகியவற்றை காணவும்.
- Use @Injectable({ providedIn: 'root' }) for app-wide singletons.
- Provide at a component when you need isolated instances.
- Use inject() in functions like route guards to retrieve dependencies outside constructors.
Service Basics
Classes-ஐ @Injectable() உடன் decorate செய்யவும் (அவை மற்ற services inject செய்யும் போது required).
Services-ஐ components-ல் use செய்ய constructors-ல் inject செய்யவும்.
Shared singleton-க்கு providedIn: 'root' பயன்படுத்தவும்.
Service Basics Syntax
@Injectable({ providedIn: 'root' })
export class DataService {}
// class App { constructor(private data: DataService) {} }
Example
Service Basics Example
import { bootstrapApplication } from '@angular/platform-browser';
import { Component, Injectable } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class CounterService {
value = 0;
inc() { this.value++; }
dec() { this.value--; }
reset() { this.value = 0; }
}
@Component({
selector: 'app-root',
standalone: true,
template: `
<h3>Services</h3>
<p>Counter: {{ counter.value }}</p>
<button (click)="counter.inc()">+</button>
<button (click)="counter.dec()">-</button>
<button (click)="counter.reset()">Reset</button>
`
})
export class App {
constructor(public counter: CounterService) {}
}
bootstrapApplication(App);
Example Explained
- @Injectable({ providedIn: 'root' }): App-wide available singleton service register செய்கிறது.
- Inject in constructor: constructor(public counter: CounterService) service-ஐ template-க்கு expose செய்கிறது.
- Methods: Shared state update செய்ய inc() / dec() / reset() call செய்யவும்.
Notes
- Metadata required when injecting: ஒரு service மற்ற services inject செய்யும் போது, DI metadata generate செய்ய @Injectable() add செய்யவும்.
- Keep state minimal: Services-ல் large shared mutable state avoid செய்யவும்; Explicit methods மற்றும் return values பயன்படுத்தவும்.
- Standalone bootstrapping: Providers registered ஆக உள்ளதை உறுதிப்படுத்தவும் மற்றும் functional constructs-ல் inject() பயன்படுத்தவும் (e.g., guards).
Component-Provided Service (Hierarchical DI)
அதன் subtree-க்கு local instance create செய்ய component-ன் providers-ல் service provide செய்யவும்.
Sibling subtrees separate instances receive செய்கின்றன.
Component-Provided Service Syntax
@Component({ providers: [LocalCounterService] })
export class Panel {}
Example
Component-Provided Service Example
import { bootstrapApplication } from '@angular/platform-browser';
import { Component, Injectable } from '@angular/core';
import { CommonModule } from '@angular/common';
@Injectable()
export class LocalCounterService {
id = Math.floor(Math.random() * 10000);
value = 0;
inc() { this.value++; }
}
@Component({
selector: 'counter-view',
standalone: true,
template: `
<p>Service #{{ svc.id }} value: {{ svc.value }}</p>
<button (click)="svc.inc()">+1</button>
`
})
export class CounterView {
constructor(public svc: LocalCounterService) {}
}
@Component({
selector: 'panel-a',
standalone: true,
imports: [CommonModule, CounterView],
providers: [LocalCounterService],
template: `
<h4>Panel A (own provider)</h4>
<counter-view></counter-view>
<counter-view></counter-view>
`
})
export class PanelA {}
@Component({
selector: 'panel-b',
standalone: true,
imports: [CommonModule, CounterView],
providers: [LocalCounterService],
template: `
<h4>Panel B (own provider)</h4>
<counter-view></counter-view>
<counter-view></counter-view>
`
})
export class PanelB {}
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, PanelA, PanelB],
styles: [`
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; }
h4 { margin: 0 0 8px; }
button { margin-top: 6px; }
`],
template: `
<h3>Component-Provided Service (Hierarchical DI)</h3>
<p>Each panel provides its own service instance.</p>
<p>Counters inside the same panel share the instance.</p>
<p>Different panels do not.</p>
<div class="grid">
<panel-a></panel-a>
<panel-b></panel-b>
</div>
`
})
export class App {}
bootstrapApplication(App);
Example Explained
- providers: [LocalCounterService]: ஒவ்வொரு panel component அதன் subtree-க்கு அதன் சொந்த service instance பெறுகிறது.
- Within a panel: பல CounterView children அதே local instance share செய்கின்றன.
- Between panels: Panel A மற்றும் Panel B வெவ்வேறு instances கொண்டுள்ளன (வெவ்வேறு id values காணவும்).
Notes
- Multiple instances expected: ஒவ்வொரு provided component subtree அதன் சொந்த instance பெறுகிறது; siblings அதை share செய்யாது.
- Avoid circular dependencies: இரண்டு services ஒருவருக்கொருவர் inject செய்வது fail ஆகும்; common logic-ஐ third service-ல் extract செய்யவும் அல்லது redesign செய்யவும்.
Service Design Tips
Services focused மற்றும் easy to test-காக வைக்கவும்:
Avoid component coupling
Services-ல் components inject செய்யாதீர்கள்; services UI-agnostic-காக வைக்கவும்.
Expose clear APIs
Small methods plain values அல்லது Observables return செய்ய பயன்படுத்தவும்; internal state private-காக வைக்கவும்.
Configuration via tokens
Configurable values-க்கு injection tokens பயன்படுத்தவும் (unique lookup key, often a class or an InjectionToken object) testing மற்றும் reuse simplify செய்ய.
Scope deliberately
App-wide singletons-க்கு providedIn: 'root' பயன்படுத்தவும்; isolated instances-க்கு component-ல் provide செய்யவும்.