Um Serviço para Múltiplos Componentes em Angular
É bastante comum que em uma aplicação existam vários componentes que utilizam serviços. Esses componentes podem compartilhar os mesmos serviços. Por exemplo, em temas anteriores, foi criado um serviço chamado DataService
, que gerencia os dados. Agora, vamos definir um componente específico para trabalhar com esses dados. Para isso, vamos usar o projeto anterior e adicionar um novo arquivo chamado data.component.ts
na pasta src/app
.
helloapp/ ├── src/ │ ├── app/ │ │ ├── app.component.ts │ │ ├── data.component.ts │ │ ├── data.service.ts │ │ ├── log.service.ts │ ├── main.ts │ ├── index.html ├── angular.json ├── package-lock.json ├── package.json └── tsconfig.json
Definiremos o seguinte código no arquivo data.component.ts
:
import { Component } from "@angular/core";
import { FormsModule } from "@angular/forms";
import { DataService } from "./data.service";
import { LogService } from "./log.service";
@Component({
selector: "data-comp",
standalone: true,
imports: [FormsModule],
providers: [DataService, LogService],
template: `<div>
<div>
<input [(ngModel)]="newItem" />
<button (click)="addItem(newItem)">Adicionar</button>
</div>
<ul>
@for(item of items; track $index){
<li>{{ item }}</li>
}
</ul>
</div>`,
})
export class DataComponent {
newItem: string = "";
items: string[] = [];
constructor(private dataService: DataService) {}
addItem(name: string) {
this.dataService.addData(name);
}
ngOnInit() {
this.items = this.dataService.getData();
}
}
O componente DataComponent
carrega e adiciona dados. Para trabalhar com serviços, o decorador @Component
define a seção providers
:
providers: [DataService, LogService];
O código do log.service.ts
mantém o mesmo do tema anterior:
export class LogService {
write(logMessage: string) {
console.log(logMessage);
}
}
Agora, vamos utilizar o componente DataComponent
no componente principal da aplicação, o AppComponent
:
import { Component } from "@angular/core";
import { DataComponent } from "./data.component";
@Component({
selector: "my-app",
standalone: true,
imports: [DataComponent],
template: `<data-comp></data-comp> <data-comp></data-comp>`,
})
export class AppComponent {}
Neste código, o componente principal chama o DataComponent
duas vezes através do elemento data-comp
. Isso significa que para cada instância do componente, um novo objeto DataComponent
será criado.
Ao executar a aplicação e tentar adicionar um novo item, a funcionalidade se comporta da seguinte maneira:
Como podemos ver, o componente DataComponent
é instanciado duas vezes, e cada instância possui seu próprio estado. Portanto, cada componente é independente e não compartilha dados com outros componentes. Portatno, ao adicionar um item em um dos componentes, ele será adicionado apenas naquele componente.
Esse comportamento pode não ser o mais adequado em todos os casos. Pode ser necessário que os componentes compartilhem o mesmo objeto de serviço, em vez de criar um novo para cada componente. Para fazer isso, podemos registrar os serviços no componente pai, o AppComponent
, em vez de registrá-los em cada componente individual:
import { Component } from "@angular/core";
import { DataComponent } from "./data.component";
import { DataService } from "./data.service";
import { LogService } from "./log.service";
@Component({
selector: "my-app",
standalone: true,
imports: [DataComponent],
providers: [DataService, LogService],
template: `<data-comp></data-comp> <data-comp></data-comp>`,
})
export class AppComponent {}
Com isso, podemos remover a declaração dos serviços do componente DataComponent
:
import { Component } from "@angular/core";
import { FormsModule } from "@angular/forms";
@Component({
selector: "data-comp",
standalone: true,
imports: [FormsModule],
template: `<div>
<div>
<input [(ngModel)]="newItem" />
<button (click)="addItem(newItem)">Adicionar</button>
</div>
<ul>
@for(item of items; track $index){
<li>{{ item }}</li>
}
</ul>
</div>`,
})
export class DataComponent {
newItem: string = "";
items: string[] = [];
constructor(private dataService: DataService) {}
addItem(name: string) {
this.dataService.addData(name);
}
ngOnInit() {
this.items = this.dataService.getData();
}
}
Agora, ambos os objetos DataComponent
usarão a mesma instância do serviço DataService
. Portanto, ao adicionar um item em um componente, ele será automaticamente refletido no outro.