Через некоторое время с AngularJS мой новый проект требует от меня использования Angular 7, поэтому я решил использовать его. Проблема, с которой я столкнулся, заключается в обмене данными между двумя несвязанными компонентами и соответствующем обновлении их HTML. Поэтому для этого я построил следующий сервис:
import { FilterSet } from './../model/filterset.model';
import { TimeData } from './../model/timedata.model';
import { FetchDataService } from './fetchQualityData.service';
import { ConfigService } from './config.service';
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
@Injectable()
export class SidebarService {
public qualityData;
public configData;
public filterSet: FilterSet;
public filterColor;
public filterModel;
public timePeriodSelected;
public timeData: TimeData;
constructor(
private _configService: ConfigService,
private _qDataSerivce: FetchDataService
) {
this.timeData = {
chosenTimeAxis: 0,
chosenTimePeriod: 2,
chosenDataSet: 0,
timePeriodEnd: '2017-03-27'
};
this.qualityData = null;
this.filterSet = null;
this.filterColor = null;
this.filterModel = null;
this.getConfig();
}
getFilterSet() {
return this.filterSet;
}
getQualityData() {
return this.qualityData;
}
getTimeData() {
return this.timeData;
}
getFilterModel() {
return this.filterModel;
}
getFilterColor() {
return this.filterColor;
}
setFilterSet(data) {
this.filterSet = data;
}
setQualityData(data) {
this.qualityData = data;
}
setTimeData(data) {
this.timeData = data;
}
setFilterModel(data) {
this.filterModel = data;
}
setFilterColor(data) {
this.filterColor = data;
}
getQData(endDate) {
const startDate = this._qDataSerivce.calculateStartDate(
this.timeData.chosenTimePeriod,
this.timeData.timePeriodEnd
);
this._qDataSerivce
.fetchData(
this.configData.dataURL,
this.configData.user,
startDate,
endDate
)
.subscribe((response: any) => {
this.setQualityData(
this._qDataSerivce.dataProcessingManageObjects(response)
);
this.setFilterSet(this._qDataSerivce.getFilters(this.getQualityData()));
});
}
getConfig() {
this._configService.fetchConfig().subscribe((data: any) => {
this.configData = data;
this.getQData(this.timeData.timePeriodEnd);
});
}
receiveDataSet(data) {
this.timeData.chosenDataSet = data;
}
receiveFilterSet(data) {
console.log(this.filterColor);
this.filterColor = this.filterSet.colors[data.color];
this.filterModel = this.filterSet.models[data.model];
if (data.color === 0) {
this.filterColor = null;
}
if (data.model === 0) {
this.filterModel = null;
}
}
receiveTimeAxis(data) {
this.timeData.chosenTimeAxis = data;
}
receiveTimePeriod(data) {
this.timeData.chosenTimePeriod = data;
const startDate = this._qDataSerivce.calculateStartDate(
this.timeData.chosenTimePeriod,
this.timeData.timePeriodEnd
);
this._qDataSerivce
.fetchData(
this.configData.dataURL,
this.configData.user,
startDate,
this.timeData.timePeriodEnd
)
.subscribe((response: any) => {
this.setQualityData(
this._qDataSerivce.dataProcessingManageObjects(response)
);
this.setFilterSet(this._qDataSerivce.getFilters(this.getQualityData()));
});
}
receiveTimePeriodEnd(endDate) {
this.timeData.timePeriodEnd = endDate;
this.getQData(endDate);
}
}
Чего я пытаюсь добиться с помощью этой службы, так это того, что когда я что-то меняю на боковой панели, другие компоненты, использующие данные из этой службы (которые они взяли с помощью get), должны быть обновлены, чтобы отражать изменения на боковой панели. И сейчас, когда я получаю новые данные с сервера, ни мои элементы боковой панели, ни другие элементы компонентов не обновляются, данные внутри них всегда остаются нулевыми, как это было при инициализации службы. Независимо от того, устанавливаю ли я this.filterSet, например, с новыми данными, компоненты не будут обновляться.
Вот мой код компонента боковой панели
@Component({
selector: 'app-sidebar',
templateUrl: './sidebar.component.html',
styleUrls: ['./sidebar.component.scss']
})
export class SidebarComponent implements OnInit, OnChanges {
dataSetEvent;
filterEvent;
timeAxisEvent;
timePeriodEvent;
timePeriodEndEvent;
filterSet: FilterSet;
endOfTimePeriod = '2017-03-27';
dataSets: Filter[];
colors: Filter[];
models: Filter[];
timeAxis: Filter[];
timePeriods: Filter[];
colorSelected: Number;
modelSelected: Number;
dataSetSelected: Number;
timeAxisSelected: Number;
timePeriodSelected: Number;
xAxisSwitchNotAvailable: Boolean;
constructor(private sidebarService: SidebarService) {}
ngOnInit() {
// this.sidebarService
// .getFilterSet()
// .subscribe(filterSet => (this.filterSet = filterSet));
this.filterSet = this.sidebarService.getFilterSet();
this.xAxisSwitchNotAvailable = false;
this.timePeriods = [
// {
// id: 0,
// name: "Day"
// },
{
id: 1,
name: 'Week'
},
{
id: 2,
name: 'Month'
},
{
id: 3,
name: 'Year'
}
];
this.timePeriodSelected = 2;
this.dataSets = [
{
id: 0,
name: 'Quality Trend (Touch)'
},
{
id: 1,
name: 'Quality Trend (No-Touch)'
}
];
this.dataSetSelected = 0;
this.timeAxis = [
{
id: 0,
name: 'Date'
},
{
id: 1,
name: 'Weekdays'
}
];
this.timeAxisSelected = 0;
}
ngOnChanges() {
if (this.filterSet != null) {
this.colors = [];
for (let i = 0; i < this.filterSet.colors.length; i++) {
this.colors.push({
id: i,
name: this.filterSet.colors[i]
});
}
this.models = [];
for (let i = 0; i < this.filterSet.models.length; i++) {
this.models.push({
id: i,
name: this.filterSet.models[i]
});
}
} else {
this.colors = [
{
id: 0,
name: 'none'
}
];
this.colorSelected = 0;
this.models = [
{
id: 0,
name: 'none'
}
];
this.modelSelected = 0;
}
}
onDataChange() {
this.sidebarService.receiveDataSet(this.dataSetSelected);
}
onFilterChange() {
const filterSetNo = {
model: this.modelSelected,
color: this.colorSelected
};
this.sidebarService.receiveFilterSet(filterSetNo);
}
onTimeAxisChange() {
this.sidebarService.receiveTimeAxis(this.timeAxisSelected);
}
onTimePeriodChange() {
if (this.timePeriodSelected === 3) {
this.xAxisSwitchNotAvailable = true;
this.timeAxisSelected = 0;
this.sidebarService.receiveTimeAxis(this.timeAxisSelected);
} else {
this.xAxisSwitchNotAvailable = false;
}
this.sidebarService.receiveTimePeriod(this.timePeriodSelected);
}
updatePeriod() {
this.sidebarService.receiveTimePeriodEnd(this.endOfTimePeriod);
}
Как видите, я получаю this.filterSet, который является объектом, с помощью функции get службы. Но после того, как я получу начальное значение, оно останется прежним в компоненте боковой панели, независимо от того, изменю ли я его в сервисе.
Я пытался использовать наблюдаемые и ретурировать (данные) и подписаться на это, но безуспешно. Я проверил, получаю ли я данные и установлен ли this.filterSet с новыми данными в службе, что есть (и было, когда я не использовал функции набора и напрямую назначал ему новые данные).
Что я делаю не так?
BehaviorSubject
в сервисе и подписаться на него в своих компонентах. Таким образом, вы получаете всех подписчиков, имеющих одинаковое значение (даже тех, которые подписались после того, как значения были отправлены.next()
). Имейте в виду, что вы должны использовать либоprovideIn: 'root'
в Injectable службы, либо предоставлять эту услугу в той же области, в которой требуется значение ( потому что наличие нескольких экземпляров службы приводит к множеству субъектов). - person Sergey   schedule 19.02.2019