Перейти к содержанию

Один сервис для всех компонентов

Вполне возможно, что в нашем приложении будет несколько различных компонентов, которые используют сервисы. При этом компоненты могут использовать одни и те же сервисы. Например, в прошлых темах был создан сервис DataService, который управляет данными. Определим специальный компонент для работы с данными. Для этого возьмем проект из прошлой темы и добавим в папку src/app новый файл data.component.ts:

Один сервис для всех компонентов

Определим в этом файле следующий код:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import { Component, OnInit } from '@angular/core';
import { DataService } from './data.service';
import { LogService } from './log.service';
import { Phone } from './phone';

@Component({
    selector: 'data-comp',
    template: `
        <div class="panel">
            <div class="form-inline">
                <div class="form-group">
                    <input
                        class="form-control"
                        [(ngModel)]="name"
                        placeholder="Модель"
                    />
                    <input
                        type="number"
                        class="form-control"
                        [(ngModel)]="price"
                        placeholder="Цена"
                    />
                    <button
                        class="btn btn-default"
                        (click)="addItem(name, price)"
                    >
                        Добавить
                    </button>
                </div>
            </div>
            <table class="table table-striped">
                <tr *ngFor="let item of items">
                    <td>{{ item.name }}</td>
                </tr>
            </table>
        </div>
    `,
})
export class DataComponent implements OnInit {
    items: Phone[] = [];
    constructor(private dataService: DataService) {}

    addItem(name: string, price: number) {
        this.dataService.addData(name, price);
    }
    ngOnInit() {
        this.items = this.dataService.getData();
    }
}

DataComponent загружает и добавляет данные. Для работы с сервисами декоратор Component определяет секцию providers:

1
providers: [DataService, LogService];

Используем этот компонент DataComponent в главном компоненте приложения AppComponent:

1
2
3
4
5
6
7
8
9
import { Component } from '@angular/core';

@Component({
    selector: 'my-app',
    template: `
        <data-comp></data-comp> <data-comp></data-comp>
    `,
})
export class AppComponent {}

Этот компонент через элемент data-comp вызывает компонент DataComponent. Причем вызывает два раза. То есть для обработки каждого элемента будет создаваться свой объект DataComponent.

И соответственно изменим главный модуль приложения AppModule:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { DataComponent } from './data.component';

@NgModule({
    imports: [BrowserModule, FormsModule],
    declarations: [AppComponent, DataComponent],
    bootstrap: [AppComponent],
})
export class AppModule {}

Теперь запустим приложение и попробуем добавить новый элемент:

Скриншот

Как видно на скриншоте, при добавлении в одном компоненте новый элемент будет добавляться только для этого компонента. Потому что у нас два отдельных компонента, и для каждого из них будет создаваться свой набор сервисов DataService и LogService.

Такое поведение не всегда может быть предпочтительным. Возможно, потребуется, чтобы компоненты использовали один и тот же объект сервиса, вместо создания разных сервисов для каждого компонента. Для этого мы можем зарегистрировать все сервисы не в компоненте, а в главном модуле приложения AppModule:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { DataComponent } from './data.component';
import { DataService } from './data.service';
import { LogService } from './log.service';
@NgModule({
    imports: [BrowserModule, FormsModule],
    declarations: [AppComponent, DataComponent],
    providers: [DataService, LogService], // регистрация сервисов
    bootstrap: [AppComponent],
})
export class AppModule {}

В этом случае мы уже можем убрать регистрацию сервисов из компонента DataComponent:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import { Component, OnInit } from '@angular/core';
import { DataService } from './data.service';
import { LogService } from './log.service';
import { Phone } from './phone';

@Component({
    selector: 'data-comp',
    template: `
        <div class="panel">
            <div class="form-inline">
                <div class="form-group">
                    <input
                        class="form-control"
                        [(ngModel)]="name"
                        placeholder="Модель"
                    />
                    <input
                        type="number"
                        class="form-control"
                        [(ngModel)]="price"
                        placeholder="Цена"
                    />
                    <button
                        class="btn btn-default"
                        (click)="addItem(name, price)"
                    >
                        Добавить
                    </button>
                </div>
            </div>
            <table class="table table-striped">
                <tr *ngFor="let item of items">
                    <td>{{ item.name }}</td>
                </tr>
            </table>
        </div>
    `,
})
export class DataComponent implements OnInit {
    items: Phone[] = [];
    constructor(private dataService: DataService) {}

    addItem(name: string, price: number) {
        this.dataService.addData(name, price);
    }
    ngOnInit() {
        this.items = this.dataService.getData();
    }
}

После этого оба объекта DataComponent будут использовать один и тот же сервис DataService. Поэтому добавление объекта в одном компоненте автоматически отразится и на другом:

Скриншот

Комментарии