У меня есть страница, которая получает массив данных о загрузке страницы и отображает его с помощью директивы *ngFor. Также существует соединение с веб-сокетом для получения обновленных данных. В этом примере это расписание морских прогулок. Моя проблема в том, что я не знаю, как обновить данные загрузки страницы новыми данными из WS. Пока у меня есть этот код:
timeTableService.service.ts - сервис для получения исходных данных о загрузке страницы
import { Injectable } from '@angular/core';
import { ApiService } from './api.service';
@Injectable()
export class TimeTableService {
constructor(
private apiService: ApiService,
) { }
getInitialTimes() {
return this.apiService.get('/timetable/')
}
}
liveTimeTableService.service.ts - сервис для подключения дескриптора подключения к веб-сокету с использованием эта библиотека
import { Injectable } from '@angular/core'
import { QueueingSubject } from 'queueing-subject'
import { Observable } from 'rxjs/Observable'
import websocketConnect from 'rxjs-websockets'
import 'rxjs/add/operator/share'
@Injectable()
export class LiveTimeTableService {
private inputStream: QueueingSubject<any>
public messages: Observable<any>
public connect() {
this.messages = websocketConnect(
'ws://www.timetables.com:8080',
this.inputStream = new QueueingSubject<string>()
).messages.share()
}
public send(message: string):void {
this.inputStream.next(message)
}
}
timeTable.component.ts - компонент для отображения расписания
import { Component, OnInit } from '@angular/core';
import { TimeTableService, LiveTimeTableService } from './shared';
import { Subscription } from 'rxjs/Subscription'
@Component({
selector: 'app-time-table',
templateUrl: './time-table.component.html',
})
export class TimeTableComponent implements OnInit {
private timeTable: any;
private socketSubscription: Subscription
constructor(
private timeTableService: TimeTableService,
private liveTimeTableService: LiveTimeTableService,
) {}
ngOnInit() {
this.liveTimeTableService.connect();
this.liveTimeTableService.send('SUBSCRIBE times')
// subscribe to any message updates
this.socketSubscription = this.liveTimeTableService.messages
.subscribe((timesUpdate) => {
this.timeTable = timesUpdate;
})
// get the time table data on page load
this.timeTableService.getInitialTimes()
.subscribe((timeTable) => {
this.timeTable = timeTable
})
}
ngOnDestroy() {
this.socketSubscription.unsubscribe()
}
}
HTML-шаблон
<div *ngFor = "let boat of timeTable">
{{ boat.name }}
<span *ngFor = "let time of boat.times">{{time}}</span>
</ldiv>
И данные выглядит так
Данные сообщения WS (содержит незначительные обновления, такие как время и статус):
Проблема в том, что this.timeTable сбрасывается каждый раз, когда приходит новое сообщение от WS, и вся директива *ngFor запускается снова и перестраивает dom. Я хотел обновить любое выражение «время» в *ngFor новыми значениями из сообщения WS, а затем применить класс css для уведомления пользователей об изменении:
Буду очень признателен за любые советы или предложения, как я могу активировать это. И извинения за очень длинный пост!





Возможно, используя параметр trackBy, как в этом ответе:
Angular 2 - с ngFor можно ли обновлять значения без перестройки dom?
Итак, ваш код будет примерно таким:
Вид:
<div *ngFor = "let boat of timeTable; let i = index; trackBy: trackByFn">
{{ boat.name }}
<span *ngFor = "let time of boat.times">{{time}}</span>
</div>
Составная часть
trackByFn(index, item) {
return index;
}
В качестве справки вы должны использовать: https://angular.io/guide/template-syntax#ngfor-with-trackby