mazdik / ng-mazdik

Angular UI component library
https://mazdik.github.io/ng-mazdik
MIT License
89 stars 34 forks source link

Do data table support "Dynamic column loading" #44

Closed suryakanta101 closed 5 years ago

suryakanta101 commented 5 years ago

Hello @mazdik

Can you suggest , how can we support to load "Columns" from Database ?

Do we need to have separate API call for column definition , because i am seeing the columns get initialize before the data load.

constructor(private http: HttpClient) { this.columns = getTreeColumns(); this.dataTable = new DataTable(this.columns, this.settings, null);

mazdik commented 5 years ago

For example, you can:

<app-data-table *ngIf="table" [table]="table"></app-data-table>

ngOnInit() {
  this.http.get(url).subscribe((data: any[]) => {
    ...
    this.table = new DataTable(this.columns, this.settings);
  }
}
mazdik commented 5 years ago

sample

import { Component, OnInit, OnDestroy } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Column, Settings, DataTable } from '../shared/lib/ng-data-table';
import { AppConfig } from '../core/app-config';
import { toISOStringIgnoreTZ } from '../shared/util';
import { SharingService } from '../shared/services/sharing.service';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-metering-detail',
  template: `
    <div *ngIf="loading" class="app-root-loader"></div>
    <app-data-table *ngIf="table" [table]="table"></app-data-table>
  `
})
export class MeteringDetailComponent implements OnInit, OnDestroy {

  ddate: Date;
  itemId: number;
  table: DataTable;
  columns: Column[] = [];
  settings: Settings = <Settings>{};
  loading: boolean;
  private subscriptions: Subscription[] = [];

  constructor(private http: HttpClient, private sharingService: SharingService) {
    this.ddate = this.sharingService.merDate;
  }

  ngOnInit() {
    this.load();
    this.subscriptions.push(this.sharingService.dateSource$.subscribe((val) => {
      this.ddate = val;
      this.load();
    }));
  }

  ngOnDestroy() {
    this.subscriptions.forEach(s => s.unsubscribe());
  }

  loadTable(rows: any[]) {
    if (rows && rows.length) {
      const keys: any[] = Object.keys(rows[0]);
      for (const key of keys) {
        if (rows[0][key] && typeof rows[0][key] === 'object') {
          const deepKeys: any[] = Object.keys(rows[0][key]);
          for (const deepKey of deepKeys) {
            this.columns.push(<Column>{
              name: key + '.' + deepKey,
              title: deepKey,
            });
          }
        } else {
          this.columns.push(<Column>{
            name: key,
            title: key,
          });
        }
      }
      // Remove duplicate
      this.columns = this.columns.filter((item, index) => {
        return index === this.columns.findIndex((x) => x.title === item.title);
      });
      this.table = new DataTable(this.columns, this.settings);
      this.table.pager.perPage = 20;
    }
  }

  load() {
    if (!this.itemId) { return; }
    const url = AppConfig.settings.host + '/detail/calc?id=' + this.itemId +
      '&beginDate=' + toISOStringIgnoreTZ(this.ddate).slice(0, 10);
    this.loading = true;
    this.http.get(url).subscribe((data: any[]) => {
      if (!this.table && data && data.length) {
        this.loadTable(<any[]>data);
      }
      if (this.table) {
        this.table.rows = data;
      }
      this.loading = false;
    },
      (err) => { this.loading = false; },
      () => { this.loading = false; });
  }

}
suryakanta101 commented 5 years ago

Thank you @mazdik

Can you help me the Sample JSON format , that work above example. It will help me to relate the logic.

Thanks.

mazdik commented 5 years ago

any JSON format from the first line of the array Object.keys(rows[0]);

if (rows && rows.length) {
      const keys: any[] = Object.keys(rows[0]);
      for (const key of keys) {
        if (rows[0][key] && typeof rows[0][key] === 'object') {
          const deepKeys: any[] = Object.keys(rows[0][key]);
          for (const deepKey of deepKeys) {
            this.columns.push(<Column>{
              name: key + '.' + deepKey,
              title: deepKey,
            });
          }
        } else {
          this.columns.push(<Column>{
            name: key,
            title: key,
          });
        }
      }

you can also describe the column on the backend