Angular2 — обмен данными между компонентами с помощью сервисов

У меня есть объект, которым я хочу поделиться между своими компонентами в приложении Angular2.

Вот исходник первого компонента:

/* app.component.ts */

// ...imports
import {ConfigService} from './config.service';

@Component({
    selector: 'my-app',
    templateUrl: 'app/templates/app.html',
    directives: [Grid],
    providers: [ConfigService]
})
export class AppComponent {
    public size: number;
    public square: number;

    constructor(_configService: ConfigService) {
        this.size = 16;
        this.square = Math.sqrt(this.size);

        // Here I call the service to put my data
        _configService.setOption('size', this.size);
        _configService.setOption('square', this.square);
    }
}

и второй компонент:

/* grid.component.ts */

// ...imports
import {ConfigService} from './config.service';

@Component({
    selector: 'grid',
    templateUrl: 'app/templates/grid.html',
    providers: [ConfigService]
})
export class Grid {
    public config;
    public header = [];

    constructor(_configService: ConfigService) {
        // issue is here, the _configService.getConfig() get an empty object 
        // but I had filled it just before
        this.config = _configService.getConfig();
    }
  }

и, наконец, мой маленький сервис, ConfigService:

/* config.service.ts */

import {Injectable} from 'angular2/core';

@Injectable()
export class ConfigService {

    private config = {};

    setOption(option, value) {
        this.config[option] = value;
    }

    getConfig() {
        return this.config;
    }
}

Мои данные не разделены, в grid.component.ts строка _configService.getConfig() возвращает пустой объект, но он заполняется непосредственно перед app.component.ts.

Я читал документы и учебники, ничего не получилось.

Что мне не хватает?

Спасибо

РЕШЕНО

Моя проблема заключалась в том, что я дважды вводил свой ConfigService. В бутстрапе приложения и в файле, где я им пользуюсь.

Я удалил настройку providers, и это сработало!


person keversc    schedule 08.02.2016    source источник
comment
В качестве примечания рассмотрите возможность перемещения вызовов службы из конструктора.   -  person Standaa - Remember Monica    schedule 26.10.2016


Ответы (3)


Вы определяете его в своих двух компонентах. Таким образом, услуга не является общей. У вас есть один экземпляр для компонента AppComponent и еще один для компонента Grid.

@Component({
  selector: 'my-app',
  templateUrl: 'app/templates/app.html',
  directives: [Grid],
  providers: [ConfigService]
})
export class AppComponent {
  (...)
}

Быстрое решение — удалить атрибут providers для компонента Grid... Таким образом, экземпляр службы будет совместно использоваться компонентами AppComponent и его дочерними компонентами.

Другое решение — зарегистрировать соответствующего провайдера в функции bootstrap. В этом случае экземпляр будет общим для всего приложения.

bootstrap(AppComponent, [ ConfigService ]);

Чтобы понять, зачем вам это нужно, вам нужно знать о функции «иерархических инжекторов» в Angular2. Следующие ссылки могут быть полезны:

person Thierry Templier    schedule 08.02.2016
comment
ОК, на самом деле у меня есть и то, и другое... В начальной загрузке и в провайдерах в каждом файле, который я хочу. Это может быть моя проблема, так что. Я проверяю это как можно скорее и сообщаю вам, была ли проблема в этом. - person keversc; 08.02.2016
comment
Да, но вам это не нужно. Когда вы настраиваете своих поставщиков, областью связанного экземпляра будет элемент и его подэлементы. При повторном определении будет воссоздан новый экземпляр. Например, если вы определяете своего провайдера в начальной загрузке, а один в компоненте, у вас будет два экземпляра службы: один на уровне приложения и один на уровне компонента. - person Thierry Templier; 08.02.2016
comment
Если вы определяете только на уровне приложения, все компоненты могут использовать этот экземпляр путем внедрения зависимостей. Это потому, что инжектор компонента является вспомогательным инжектором или прикладным. Они используют прототипное наследование. Ребенок может видеть элементы в родительском - person Thierry Templier; 08.02.2016
comment
Хорошо, спасибо за ссылки и пояснения, мне нужно больше узнать об услугах, прежде чем продолжить! - person keversc; 08.02.2016
comment
Пожалуйста! На самом деле важной проблемой здесь являются иерархические инжекторы ;-) Если вы определяете дважды, вы больше не используете поставщика родителя... - person Thierry Templier; 08.02.2016
comment
Возвращаясь к вам, это была моя проблема. Это решено сейчас. Еще раз спасибо - person keversc; 09.02.2016
comment
Спасибо @ThierryTemplier - это именно то, что я искал. А как же братья и сестры? Они оба используют родительский сервис? - person itamar; 10.08.2016
comment
Пожалуйста! Если у вас есть поставщик услуг в родительском компоненте, все дочерние компоненты будут совместно использовать эту службу. В противном случае нет. Это из-за иерархических инжекторов Angular2... - person Thierry Templier; 10.08.2016
comment
Возможно, этот вопрос может вас заинтересовать: stackoverflow.com/questions/34804298/ - person Thierry Templier; 10.08.2016
comment
Откуда вы импортируете функцию начальной загрузки? Я не могу найти это в документах - person avoliva; 30.12.2016
comment
Ты герой современности - person Sam Alexander; 22.05.2017

Для последней версии angular, если вы хотите поделиться сервисом, вы не можете добавить его в функцию начальной загрузки. Просто добавьте его в список провайдеров NgModule, как если бы вы делали это с обычным сервисом, его поведение по умолчанию будет одноэлементным.

начальная загрузка (AppComponent);

@NgModule({
    declarations: [
        ....
    ],
    imports: [
       ....     
    ],
    providers: [
        ConfigService,
....
person Mike D    schedule 18.10.2016

Не добавляйте ConfigService к providers вашего компонента. Это приводит к новым экземплярам для каждого компонента. Добавьте его в providers общего родительского компонента. Если вы добавите его в свой корневой компонент или bootstrap(App, [ConfigService]), все ваше приложение будет использовать один экземпляр.

person Günter Zöchbauer    schedule 08.02.2016
comment
Хорошо, спасибо, я посмотрю на это, пока у меня есть ConfigService как в начальной загрузке, так и в файле, это может быть моя проблема. Я попробую это как можно скорее - person keversc; 08.02.2016