After creating a component and service in my project, I followed the documentation's instruction to include the service in the providers metadata of the component for injection. However, I found that it still works fine even without mentioning it in the metadata. This has left me puzzled as to why this is happening.
I came across a similar discussion on StackOverflow regarding this issue in a related question
The explanation provided was that if the service is not specified in the component where it is being used, Angular will look for it upwards in the hierarchy until it finds the instance, starting from its parent component up to the module where it's used. Each level maintains its own map of provider instances, and the component will use the first instance it encounters during traversing the injection tree upwards.
I searched through my entire application to verify this behavior but couldn't find anything confirming it.
Component module: card.component.ts
import { Component, OnInit, Input, OnChanges, SimpleChanges } from '@angular/core';
import { BoxesService } from '../boxes.service';
import { Box } from '../box';
import { HeaderTitleService } from '../header-title.service';
@Component({
selector: 'app-card',
templateUrl: './card.component.html',
styleUrls: ['./card.component.css'],
providers: []
})
export class CardComponent implements OnInit {
public selectedBox: Box = { name : '', text : '', id:0};
public boxes: Box[] = [];
private header = "Total Cards displayed : " + this.boxes.length;
constructor(private boxData: BoxesService, private headerService: HeaderTitleService) { }
private getBoxes(): void {
this.boxes = this.boxData.getBoxes();
}
public ngOnInit(): void {
this.getBoxes();
this.header = "Total Cards displayed : " + this.boxes.length;
this.headerService.setTitle(this.header);
}
public onClick(box: Box) {
this.selectedBox = box;
}
}
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { CardComponent } from './card/card.component';
import { HeaderComponent } from './header/header.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { CardDetailComponent } from './card-detail/card-detail.component';
@NgModule({
declarations: [
AppComponent,
CardComponent,
HeaderComponent,
DashboardComponent,
CardDetailComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Service class: boxes.service.ts
import { Injectable } from '@angular/core';
import { Box } from './box';
@Injectable({
providedIn: 'root'
})
export class BoxesService {
private boxes : Box[] = [
{ name: 'box1', text: 'test data for box 1', id: 1 },
{ name: 'box2', text: 'test data for box 2', id: 2 },
{ name: 'box3', text: 'test data for box 3', id: 3 },
{ name: 'box4', text: 'test data for box 4', id: 4 },
{ name: 'box5', text: 'test data for box 5', id: 5 },
{ name: 'box6', text: 'test data for box 6', id: 6 },
{ name: 'box7', text: 'test data for box 7', id: 7 },
{ name: 'box8', text: 'test data for box 8', id: 8 },
{ name: 'box9', text: 'test data for box 9', id: 9 },
{ name: 'box10', text: 'test data for box 10', id: 10 },
]
getBoxes(): Box[]{
return this.boxes;
}
constructor() { }
}
Trying to wrap my head around this concept has been a challenge, and I've been stuck on it for the past day.