ng2-table icon indicating copy to clipboard operation
ng2-table copied to clipboard

Nested column.name nullable

Open mikapomet opened this issue 8 years ago • 5 comments

I tried to display nested data with changing structure.

public data:Array<any> = [
  {
      name: 'John',
      wife: {
          name: 'Jane'
      }
  },
  {
      name: 'Doe',
  }
];

public columns:Array<any> = [
    {title: 'UserName', name: 'name'},
    {title: 'WifeName', name: 'wife.name'}
  ];

Displayed data are breaked beacause of the getData decaration in components/table/ng-table.component.js.
Actually It's declared as :

public getData(row:any, propertyName:string):string {
	return propertyName.split('.').reduce((prev:any, curr:string) => prev[curr], row);
}

What about remplacing it by :

public getData(row:any, propertyName:string):string {
	let a = propertyName.split('.');
        for (var i = 0, n = a.length; i < n; ++i) {
            let k = a[i];
            if (row != null && k in row) {
                row = row[k];
            }
        }
    return row;
}

This way, both wife block missing and null value work.

mikapomet avatar Apr 20 '17 13:04 mikapomet

I modify getData return following

return propertyName.split('.').reduce(function (prev, curr) { if (prev[curr] != undefined || prev[curr] != null) return prev[curr]; else return ''; }, row);

and it will block null value work.

qwe852147 avatar Apr 21 '17 08:04 qwe852147

Solution provided by @qwe852147 did not working for me. My prop value is null. I have also tried:

  public getData(row: any, propertyName: string): string {
    if (propertyName !== null) {
      return propertyName.split('.').reduce((prev: any, curr: string) => prev[curr], row);
    } else {
      return '';
    }
  }

with no effect

TeodorKolev avatar Jul 17 '17 09:07 TeodorKolev

I also have nullables value from the DB that cause ngtable to break. My solution was to check each string (they were strings in my case) and if they were nullable save in the rows an empty string instead.

Hope it helps. Mese

themese avatar Jul 17 '17 09:07 themese

@themese How you achieve that?

TeodorKolev avatar Jul 17 '17 10:07 TeodorKolev

So, my approach is to first retrieve the data from the DB and then set the rows in a function. Imagine a 2 columns table where the first columns is Id - not nullable- and the second one is the name - nullable, because some business logic behind it demands it.

// variables
    private columns = [
        { title: "Id", name: "id"},
        { title: "Name", name: "name"}
    ];
    private rows: any[];
    private _dataFromDB: any[]; // the data retrieved from the DB, probably you will retrieve it calling a service in the retrieveDataFromDB() function
    private _tableData: any[]; // this will be the data used to populate the table rows
    (...)
    private retrieveDataFromDB(): void {
        (...)
        this.fooOnceDataIsLoaded();
    }
    private fooOnceDataIsLoaded(): void {
        (...)
        this.setRows();
    }
    private setRows(): void {
        this._data.forEach( element => {
            let obj = {
                "id": element.id,
                "name": element.name ? element.name : ""
            };
            this._tableData.push(obj);
        });
        this.rows = this._tableDatal;
    }

We could just add to .this.rows the data from the DB, but with my approach you can check for nulls/undefinded and also add checkboxes/buttons/custom elements that vary depending of the datatable to the table.

Let me know if it was unclear, it might be a bit messy. Also keep in mind I'm using too much "any" and voids, probably there is a cleaner way to do it.

Mese

themese avatar Jul 17 '17 11:07 themese