Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serving up data for treetable via async obervable #24

Open
jh0274 opened this issue May 31, 2019 · 6 comments
Open

Serving up data for treetable via async obervable #24

jh0274 opened this issue May 31, 2019 · 6 comments

Comments

@jh0274
Copy link

jh0274 commented May 31, 2019

Hi!
This component looks great, thank you. I'm currently having issues trying to serve data to the treetable using an observable stream. I know that this works with mat-table, should it also work with your treetable?

Thanks

James

@mlrv
Copy link
Owner

mlrv commented May 31, 2019

Hi @jh0274, yes the component supports data coming in from streams, I can try to point you in the right direction if you provide an example of your use case.

@jh0274
Copy link
Author

jh0274 commented Jun 1, 2019

Hi @mlrv

thank you so much for confirming that! So the issue i'm having is that the table renders first with the data that i initialised the 'Node' property with (ie 1, a, 2 - see below) but it's not updating when the async call to the web API returns the complete dataset (via the observable stream). I know the observable stream returns the dataset because i've debugged it to the console.. any help you can give me is much appreciated! Code below..

html:

<treetable
[tree]="assets"
[options]="treeOptions"
(nodeClicked)="logNode($event)">

component.ts:

import { Component, OnInit, AfterViewInit } from '@angular/core';
import { HeroService } from '../hero.service';
import { Hero } from '../hero';
import { Asset} from '../asset';
import { Options, Node } from 'ng-material-treetable';
import { AssetsService } from '../assets.service';

@component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {

selectedHero: Hero;
onSelect(hero: Hero): void {
this.selectedHero = hero;
}

constructor(
private assetsService: AssetsService,
) { }

assets: Node = {
value: {
id: 1,
AA1: "a",
percent: 2,
},
children: []
};

errorMessage: String;

getAssets(): void {
this.assetsService.getAssets()
.subscribe(
assets => {
this.assets = assets;
},
error => this.errorMessage = error
);
}
ngOnInit() {
this.getAssets();
}
}

assets.Service.ts:

import { Injectable } from '@angular/core';

import { Observable, of } from 'rxjs';
import { MessageService } from './message.service';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { catchError, map, tap, filter, retry } from 'rxjs/operators';

import { Node } from 'ng-material-treetable';
import {Asset } from './asset';

@Injectable({
providedIn: 'root'
})
export class AssetsService {

constructor(private http: HttpClient,
private messageService: MessageService) { }

getAssets (): Observable<Node<Asset>>{
  return this.http.get<Node<Asset>>(this.assetsUrl)
    .pipe(
      tap(data => this.log('fetched assets' + JSON.stringify(data))),
    );
}

private log(message: string) {
  this.messageService.add(`AssetsService: ${message}`);
  }
  private handleError<T> (operation = 'operation', result?: T) {
    return (error: any): Observable<T> => {
  
      // TODO: send the error to remote logging infrastructure
      console.error(error); // log to console instead
  
      // TODO: better job of transforming error for user consumption
      this.log(`${operation} failed: ${error.message}`);
  
      // Let the app keep running by returning an empty result.
      return of(result as T);
    };
  }

private assetsUrl = 'api/assets';

}

in-memory-data.service.ts (Mock DB):

import { InMemoryDbService } from 'angular-in-memory-web-api';
import { Hero } from './hero';
import { Injectable } from '@angular/core';
import { Node } from 'ng-material-treetable';
import {Asset } from './asset';

@Injectable({
providedIn: 'root',
})
export class InMemoryDataService implements InMemoryDbService {
createDb() {
const assets: Node = {
value: {
id: 1,
AA1: 'Listed Equities',
percent: 15.6
},
children: [
{
value: {
id: 2,
AA1: 'Emerging Markets(ex China)',
percent: 4
},
children: []
},
{
value: {
id: 3,
AA1: 'Emerging Markets(ex China)',
percent: 4
},
children: []
},
{
value: {
id: 4,
AA1: 'Emerging Markets(ex China)',
percent: 4
},
children: []
}
]
};

return {assets};

}

@Stromwerk
Copy link
Contributor

I also have a similar issue. I load the tree structure once, but I have a way to change the current tree. When the event is triggered for the tree change and all the data is loaded from the Observables the tree still doesn't update. I've checked the network tab and the request is there and it finishes.

this.masterDataService.getItemListExplosion(indexKey, refDate, unit, true, 1)
.subscribe((itemListExplosion: IItemListExplosion[]) => {
    console.log(this.itemListExplosionToTree(itemListExplosion));
    this.treeDataStructure = this.itemListExplosionToTree(itemListExplosion);
});

This is the code in question. this.treeDataStructure is the value which is passed to the [tree] input. As you can see there is a console.log there, which logs the Tree which is then assigned to treeDataStructure. The value is logged to the console, however the tree doesn't update.

@peterjester
Copy link

peterjester commented Dec 17, 2019

Hi! Was this ever implemented/resolved? Would love to implement this tree-table in my application, however my data is dynamic. @mlrv

The use case @jh0274 used is essentially exactly what I am trying to do.

@ferhattelci
Copy link

Hi all! i'm also trying to do this and getting

node is undefined!
An error occured.
We'll work on it.
Please take a screenshot, describe how the error could occur and contact your system administrator.

This exception occurs from the validator.service, because my tree-array is undefined

Some kind of ideas?

Thanks!

@mthor
Copy link

mthor commented Dec 20, 2019

I added an *ngIf="data" and that seemed to work

<treetable *ngIf="ctCloudDepartmentService.departmentsGridData.length" [tree]="ctCloudDepartmentService.departmentsGridData" [options]="treeOptions" (nodeClicked)="logNode($event)"> </treetable>

Stromwerk pushed a commit to Stromwerk/ng-material-treetable that referenced this issue Jan 21, 2020
This commit fixes the issue of the table not
updating as the tree passed to it changed.
This is done by implementing OnChanges and
rerunning initialization code after the tree
has changed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants