Обновление изменений переменных компонентов из службы с помощью angular2
В моем приложении есть служба NameService, которая содержит имя.
Есть два дочерних компонента приложения, Navbar и TheContent, которые ссылаются на эту службу. Всякий раз, когда имя изменяется в службе, я хочу, чтобы он обновлялся в обоих остальных компонентах. Как я могу это сделать?
import {Component, Injectable} from 'angular2/core'
// Name Service
@Injectable()
class NameService {
name: any;
constructor() {
this.name = "Jack";
}
change(){
this.name = "Jane";
}
}
// The navbar
@Component({
selector: 'navbar',
template: '<div>This is the navbar, user name is {{name}}.</div>'
})
export class Navbar {
name: any;
constructor(nameService: NameService) {
this.name = nameService.name;
}
}
// The content area
@Component({
selector: 'thecontent',
template: '<div>This is the content area. Hello user {{name}}. <button (click)=changeMyName()>Change the name</button></div>'
})
export class TheContent {
name: any;
constructor(public nameService: NameService) {
this.name = nameService.name;
}
changeMyName() {
this.nameService.change();
console.log(this.nameService.name);
}
}
@Component({
selector: 'app',
providers: [NameService],
directives: [TheContent, Navbar],
template: '<navbar></navbar><thecontent></thecontent>'
})
export class App {
constructor(public nameService: NameService) {
}
}
Ответы
Ответ 1
Предоставить событие в службе и подписаться на него в компонентах:
@Injectable()
class NameService {
name: any;
// EventEmitter should not be used this way - only for `@Output()`s
//nameChange: EventEmitter<string> = new EventEmitter<string>();
nameChange: Subject<string> = new Subject<string>();
constructor() {
this.name = "Jack";
}
change(){
this.name = 'Jane';
this.nameChange.next(this.name);
}
}
export class SomeComponent {
constructor(private nameService: NameService) {
this.name = nameService.name;
this._subscription = nameService.nameChange.subscribe((value) => {
this.name = value;
});
}
ngOnDestroy() {
//prevent memory leak when component destroyed
this._subscription.unsubscribe();
}
}
См. также
angular.io - COMPONENT INTERACTION - Родитель и дети обмениваются данными через службу
Ответ 2
Так как name
в NameService
является примитивным типом, вы получите другой экземпляр в службе и ваших компонентах. Когда вы меняете name
в NameService
, свойства компонента по-прежнему имеют начальное значение, и привязка не работает должным образом.
Здесь вы должны применить угловое "правило точки" и привязать к ссылочному типу. Измените NameService
, чтобы сохранить объект, содержащий имя.
export interface Info {
name:string;
}
@Injectable()
class NameService {
info: Info = { name : "Jack" };
change(){
this.info.name = "Jane";
}
}
Вы можете привязываться к этому объекту и автоматически получать обновления для свойства name
.
// The navbar
@Component({
selector: 'navbar',
template: '<div>This is the navbar, user name is {{info.name}}.</div>'
})
export class Navbar {
info: Info;
constructor(nameService: NameService) {
this.info = nameService.info;
}
}
Ответ 3
Я думаю, что решение, предоставленное Günter, является лучшим.
Тем не менее, вы должны знать, что службы Angular2 являются одноточечными, которые имеют место в дереве инжекторов. Это означает, что:
- если вы определяете свою службу на уровне приложения (во втором параметре метода
bootstrap
), экземпляр может быть общим для всех элементов (компонентов и службы).
- если вы определяете свою службу на уровне компонента (в атрибуте
providers
), экземпляр будет специфичен для компонента и его вспомогательных компонентов.
Подробнее о таком аспекте вы можете прочитать в документе "Иерархическая зависимость": https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html
Надеюсь, это поможет вам,
Thierry