#angular #typescript #behaviorsubject
#angular #typescript #behaviorsubject
Вопрос:
Я хочу использовать brandName
переменную из родственного компонента в другой в том же модуле. Я пытался сделать это с помощью BehaviorSubject
Однако, хотя я могу отправлять обновленные brandName
данные в свою службу, мой компонент по-прежнему использует сообщение по умолчанию.
мой файл службы выглядит следующим образом:
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class DataService {
private messageSource = new BehaviorSubject('default message');
currentMessage = this.messageSource.asObservable();
constructor() { }
changeMessage(message: string) {
console.log('service sent: ' message);
this.messageSource.next(message);
}
}
здесь консоль выводит обновленное сообщение.
однако, когда я пытаюсь обновить свою переменную в компоненте Order, я получаю «сообщение по умолчанию»
Order.component.ts:
import {DataService} from '../services/data.service';
...
export class OrderComponent implements OnInit {
...
constructor(...private data: DataService)
...
this.data.currentMessage.subscribe(message => this.brandName = message);
console.log('brandname');
console.log(this.brandName);
выводит «сообщение по умолчанию»
только их общий родительский app.module.ts
элемент содержит DataService
поставщика.
Редактировать
Я попытался также получить переменную из третьего компонента, используя:
this.data.currentMessage.subscribe(сообщение => this.brandName = сообщение);
В этом случае фактически получают обновленное фирменное наименование, но в компоненте, для которого он предназначен, по-прежнему ничего нет, хотя оба компонента являются братьями и сестрами одного уровня.
Кроме того, я попытался переделать службу с помощью
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class DataService {
private data: string;
setOption(value) {
this.data = value;
console.log('service sent: ' value 'and data ' this.data );
}
getOption() {
console.log('service returned');
console.log(this.data);
return this.data;
}
Однако я сталкиваюсь с той же проблемой, когда служба получает обновленное значение, третий компонент может получить это обновленное значение, но мой компонент, для которого предназначался сервис, получает значение по умолчанию.
Комментарии:
1. можете ли вы собрать stackblitz, отображающий неправильную функциональность?
Ответ №1:
Попробуйте объявить службу, как показано ниже, чтобы иметь один экземпляр (добавить providedIn: 'root'
)
@Injectable({
providedIn: 'root',
})
export class DataService {
private messageSource = new BehaviorSubject('default message');
currentMessage = this.messageSource.asObservable();
constructor() { }
changeMessage(message: string) {
console.log('service sent: ' message);
this.messageSource.next(message);
}
}
И поскольку служба вызывается асинхронно, console.log(this.brandName);
вызывается до окончания работы службы, поэтому я предлагаю переместить this.brandName
значение журнала внутри subscribe:
this.data.currentMessage.subscribe(message => {
this.brandName = message;
console.log(this.brandName); // will show the new message
});
console.log('brandname');
console.log(this.brandName); // will show the default message
Я создал приложение Stackblitz, содержащее ваш код и в котором работает общая служба: https://stackblitz.com/edit/angular-ele1cu
Комментарии:
1. Я попытался добавить предоставленный Injectable, но я все равно получаю сообщение по умолчанию.
2. Может ли тот факт, что компонент, в котором я изменяю сообщение, загружается до того, как Order.component подписан на сообщение, означает, что оно не работает?
3. спасибо за ваш ответ, Мохамед, к сожалению, я по-прежнему получаю значение по умолчанию
this.data.currentMessage.subscribe(message => { this.brandName = message; console.log(this.brandName); // will show the new message });
, поскольку я отредактировал свой исходный пост с дополнительной информацией4. из вашего кода я заметил, что вы не вызываете
changeMessage
метод, я создал рабочий стекблитц: stackblitz.com/edit/angular-ele1cu
Ответ №2:
Вы должны предоставить эту услугу как одноэлементную на более высоком (модульном) уровне. Похоже, у вас есть два разных экземпляра этой службы.
Ответ №3:
Файл службы
import { Observable, Subject, } from 'rxjs';
@Injectable({providedIn: 'root'})
export class DataService {
// private messageSource = new BehaviorSubject('default message');
// currentMessage = this.messageSource.asObservable();
private messageSource = new Subject<string>();
constructor() { }
/*changeMessage(message: string) {
console.log('service sent: ' message);
this.messageSource.next(message);
}*/
setMessage(message: string) {
this.messageSource.next(message);
}
getMessage() {
return this.messageSource.asObservable();
}
}
Используйте метод GetMessage в службе, чтобы подписаться на изменения в сообщении в вашем компоненте, и используйте метод setMessage для установки сообщения