I have an angular service that has an array of custom objects
and an observable
of
this array.
An outside component subscribes
to the observable, but does not react when the list get's changed.
Also, the observable
is set as data source
for a mat-table
which does not react eather.
The service (uses a gRPC
stream to get data):
export class ScanService {
private scanCient: ScanClient = new ScanClient('http://' + window.location.hostname + ':8080', null, null);
private results: ItemModel[] = [];
readonly results$ = from(this.results);
constructor() { }
start(ip: string): boolean {
let stream = this.scanCient.listen(ip, {});
stream.on('data', (response) => {
this.results.push({
name: response.getName(),
type: response.getType(),
});
console.log('stream got item: ' + response.getName());
}
}
}
The consumer:
export class ScanComponent implements OnInit {
//...
results$: Observable<ItemModel[]>;
constructor(private scanService: ScanService) { }
ngOnInit() {
this.results$ = this.scanService.results$;
this.results$.subscribe({next: function(results){console.log('subscriber got item: ', results);}});
}
onScan() {
this.scanService.start(this.ip);
}
}
<table mat-table [dataSource]="results$" class="mat-elevation-z8">
In the console output
I see the stream got item
for each item, but not the subscriber got item
and also the mat-table
remains empty.
EDIT:
I have a similar example using of
that appears to work as expected.
The difference is that the gRPC
call return an object directly, not a stream.
Service:
export class DiscoveryService {
private deviceList: DeviceModel[] = [];
private discoveryCient: DiscoveryClient = new DiscoveryClient('http://' + window.location.hostname + ':8080', null, null);
constructor() {
}
getDeviceList(): void {
this.discoveryCient.devices(new EmptyProto(), {}, (err, reply) => {
const pbDeviceList = reply.getDevicesList();
for (const pbDevice of pbDeviceList) {
this.deviceList.push({ ip: pbDevice.getIp()});
}
});
}
observeDeviceList(): Observable<DeviceModel[]> {
return of(this.deviceList);
}
}
Consumer:
export class DeviceListComponent implements OnInit {
deviceList$: Observable<DeviceModel[]>;
constructor(private discoveryService: DiscoveryService) { }
ngOnInit() {
// First get the observable to the list(which is still empty)
this.deviceList$ = this.discoveryService.observeDeviceList();
// Then tell the service to populate the list
this.discoveryService.getDeviceList();
}
}
<mat-nav-list *ngFor="let device of deviceList$ | async">