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">