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

One million records

Open xianrui opened this issue 9 years ago • 21 comments

I have a data, there are one million records, how to use this component, because I found that when the data from the server to get all the data thanks

xianrui avatar Sep 20 '16 07:09 xianrui

I also face this issue, and I find that the default implementation of DataSource is LocalDataSource, so we can implement a RemoteDataSource to fetch and filter the records from the server side, is it right?

hoswey avatar Sep 21 '16 03:09 hoswey

I notice that "Local data source (Server/API DataSource is on its way)" in the wiki, is there any timeline of this feature?

hoswey avatar Sep 21 '16 05:09 hoswey

+1

PatrickHuetter avatar Sep 30 '16 12:09 PatrickHuetter

+1

sgruhier avatar Oct 07 '16 12:10 sgruhier

Hey Guys, we released a beta version of the server data source under '0.4.0-2' version. Here https://github.com/akveo/ng2-smart-table/blob/master/demo/src/app/pages/demo/components/advanced-example-server.component.ts you can find an example of how to implement it, and here https://github.com/akveo/ng2-smart-table/blob/master/src/ng2-smart-table/lib/data-source/server/server-source.conf.ts#L22 a list of configurations available for the server data source.

Please let us know if you have any questions and your feedback is much appreciated.

nnixaa avatar Oct 26 '16 14:10 nnixaa

I think you shouldn't create API adapter that assumes what would be API interface. ServerDataSource you created is a good example, but as there is no single version of proper REST API, or maybe someone would like to use Falcor or GraphQL, there is no point implementing specific API interface. Better if you made proper documentation of writing on DataSource.

sielay avatar Oct 27 '16 20:10 sielay

Hi @sielay, we definitely thought of it, that there is no standardised version of REST API and moreover there are plenty of other API interfaces. But anyway, we decided to create this one for two cases:

  1. when a user doesn't have API and could develop it in the format suggested by the library, and then just turn the ng2-smart-table on with no (or with minor) modifications.
  2. secondly working server data source is a good example (as you noticed) of creating your own.

The current version is still in the development and there is a list of modifications we need to make, but at least it gives a general idea on how to create your own API data source version for your needs. Let us know your thoughts.

nnixaa avatar Oct 28 '16 08:10 nnixaa

@nnixaa that is a good point. From what I found is that LocalDataSource is a far better example than ServerDatasource. The second is too opinionated for me. It would be nice to expose DataSource, so I don't have to extend LocalDataSource (but I can live with that). If you go further with LocalDataSource you need to add easy support for headers, as mostly authentication (like with JWT) will require it.

sielay avatar Oct 28 '16 13:10 sielay

+1 for headers support, it would be very helpful

gvital3230 avatar Oct 30 '16 15:10 gvital3230

@gvital3230 The way how I did it so far

import { Injectable } from '@angular/core';
import { Http, Headers, Response } from '@angular/http';
import { Observable } from 'rxjs';
import 'rxjs/add/operator/map'

@Injectable()
export class ApiService {
    public token: string;
    private endpoint: string = 'MYENDPOINT';

    constructor(private http: Http) {}

    private process(response:Response) {
        let json = response.json();
        if (json && json.errorMessage) {
            throw new Error(json.errorMessage);
        }
        return json;
    }

    private processError(error: any) {
        let
            errMsg = (error.message) ? error.message : error.status ? `${error.status} - ${error.statusText}` : 'Server error';
        console.error(errMsg); // log to console instead
        return Observable.throw(errMsg);
    }


    getHeaders() {
        let headers = new Headers();
        headers.append('Content-Type', 'application/json');
        if(this.token) {
            headers.append('Authorization', this.token);
        }
        return {
            headers: headers
        };
    }

    get(url) {
        return this
            .http
            .get(this.endpoint + url, this.getHeaders())
            .toPromise()
            .then(this.process)
            .catch(this.processError);
    }

    post(url, data) {
        return this
            .http
            .post(this.endpoint+ url, data, this.getHeaders())
            .toPromise()
            .then(this.process);
    }

    put(url, data) {
        return this
            .http
            .put(this.endpoint+ url, data, this.getHeaders())
            .toPromise()
            .then(this.process)
            .catch(this.processError);
    }

    apiURL(magazine) {
        return this.endpoint
    }

    delete(url) {
        return this
            .http
            .delete(this.endpoint+ url, this.getHeaders())
            .toPromise()
            .then(this.process)
            .catch(this.processError);
    }

    setToken(token) {
        localStorage.setItem('ssid', token);
        this.token = token;
    }

}

and then my source

import {Injectable} from '@angular/core';
import {ApiService} from '...';
import {LocalDataSource} from '...';

@Injectable()
export class MyTableLoadSource extends LocalDataSource {

  busy: Promise<any>;

  constructor(private api:ApiService) {
    super(null);
  }

 getElements(): Promise<any> {
    this.busy = new Promise(resolve => {});
    return this.api
        .get('SOMERESOURCE')
        .then(data => this.data = data);
  }


}

Later you can extend it by filtering etc other ideas about your API. It's not basing on latest version of code, so guys might simplified few things already.

sielay avatar Oct 31 '16 09:10 sielay

@sielay tried your code but am getting following error

EXCEPTION: Uncaught (in promise): TypeError: Cannot read property 'get' of undefined

can you please tell me what is the error, am creating a another parameter in get() for APIService and passing it in componenets

Code modified APIService

    get(url,request) {
        return this
            .http
            .get(this.endpoint + url,request, this.getHeaders())
            .toPromise()
            .then(this.process)
            .catch(this.processError);
    }

App.Component

getElements(): Promise { this.busy = new Promise(resolve => {}); return this.api .get('http://helloApi:88/api/path/GetReviewList',JSON.stringify({"VendorID": 1})) .then(data => this.data = data); }

DeveBj avatar Dec 14 '16 13:12 DeveBj

@DeveBj You need to add

import {ApiService} from '...';

and

constructor(private api:ApiService) {
  super(null);
}

cubicsrube avatar Dec 15 '16 14:12 cubicsrube

I have the above working but I'm still unable to set the pagination based on the response from the API, is this possible? i.e. set a total and page from the API so that large datasets can be partially loaded for performance?

daveykane avatar Feb 21 '17 15:02 daveykane

@daveykane Were you able to do that? Can you please share an example.

salilotr89 avatar Jun 22 '17 12:06 salilotr89

I'm trying to add total record count fetched from my first API call when the page loads initially. Based on the count I will come to know the total number of pages, and in turn based on the page click will fire appropriate API calls to populate data. Is this possible using NG2-Smart-Table? I am planning to write my own custom component for pagination and do the above task.

sdjcse avatar Jul 24 '17 23:07 sdjcse

did anyone got the solution??

Sravanti94 avatar Oct 25 '17 06:10 Sravanti94

Hi, in case it helps others too, I initially got slightly misled by @nnixaa's post from 26th Oct 2016 and thought that the ServerDataSource was only in a beta branch of the code (0.4.0-2) but I've realised it's in the main branch, with a live demo (second example at that link) and demo source (slightly different link from before). I am pretty sure that I've understood correctly that it's still a beta feature, though?

I was also wondering, would be possible to customise ServerDataSource to the user's own API by providing callbacks to allow the user to modify things just before the http call and to extract things (i.e. total rows and data objects) afterwards? (That works for customising server-side autocomplete callbacks in the Select2 library, which I've used.)

mikebeaton avatar Nov 07 '17 11:11 mikebeaton

I wrote a custom datasource to use with loopback. It's my first implementation:

import { BaseLoopBackApi, LoopBackFilter } from '../client/sdk';
import { map } from 'rxjs/operators';
import { LocalDataSource } from 'ng2-smart-table';

export class LoopbackDataSource extends LocalDataSource {

    protected lastRequestCount: number = 0;

    constructor(protected api: BaseLoopBackApi, protected columns: Object, protected idName: string = 'id') {
        super();
    }

    prepend(element: any): Promise<any> {
        return this.api.create(element).pipe(map(res => {
            return super.prepend(res);
        })).toPromise();
    }

    add(element: any): Promise<any> {
        return this.api.create(element).pipe(map(res => {
            return super.add(res);
        })).toPromise();
    }

    update(element: any, values: any): Promise<any> {
        return new Promise((resolve, reject) => {
            this.api.updateAttributes(element[this.idName], values).subscribe((result) => {
                // it's a nice trick from https://github.com/akveo/ng2-smart-table/issues/195#issuecomment-311799579
                element = Object.assign(element, result);
                this.emitOnUpdated(element);
                this.emitOnChanged('update');
                resolve();
            }, err => {
                reject(err);
            });
        });
    }

    remove(element: any): Promise<any> {
        return this.api.deleteById(element[this.idName]).pipe(map(res => {
            return super.remove(element);
        })).toPromise();
    }

    count(): number {
        return this.lastRequestCount;
    }

    getElements(): Promise<any> {
        let filter = this.addSortRequestParams({});
        filter = this.addFilterRequestParams(filter);
        filter = this.addPagerRequestParams(filter);

        this.api.count(filter.where).subscribe((result) => {
            this.lastRequestCount = result.count;
        });

        return this.api.find(filter).pipe(map(res => {
            this.data = res;
            return this.data;
        })).toPromise();
    }

    protected addSortRequestParams(filter: LoopBackFilter): LoopBackFilter {
        if (this.sortConf) {
            const order = [];
            this.sortConf.forEach((fieldConf) => {
                order.push(fieldConf.field + ' ' + fieldConf.direction.toUpperCase());
            });
            filter.order = order;
        }

        return filter;
    }

    protected addFilterRequestParams(filter: LoopBackFilter): LoopBackFilter {
        if (this.filterConf.filters) {
            const where = {};
            this.filterConf.filters.forEach((fieldConf: any) => {
                if (fieldConf['search']) {
                    if (this.columns[fieldConf['field']].type === 'string') {
                        where[fieldConf['field']] = { like: fieldConf['search'], options: 'i' };
                    } else {
                        where[fieldConf['field']] = fieldConf['search'];
                    }
                }
            });
            filter.where = where;
        }

        return filter;
    }

    protected addPagerRequestParams(filter: LoopBackFilter): LoopBackFilter {
        if (this.pagingConf && this.pagingConf['page'] && this.pagingConf['perPage']) {
            filter.skip = this.pagingConf['page'] - 1;
            filter.limit = this.pagingConf['perPage'];
        }

        return filter;
    }
}

rafaneri avatar Mar 06 '19 19:03 rafaneri

I notice that "Local data source (Server/API DataSource is on its way)" in the wiki, is there any timeline of this feature?

I have impletement Server side data source . and it is working finely, pagination is also working, just facing issue with filtering data in my ng2-smart-table.

aashishrawte1 avatar Nov 11 '21 12:11 aashishrawte1

Anyone here could tell me how can I make pagination using ng2 smart table and graphql ?

SkanderLassoued09 avatar Oct 12 '22 13:10 SkanderLassoued09

I notice that "Local data source (Server/API DataSource is on its way)" in the wiki, is there any timeline of this feature?

I have impletement Server side data source . and it is working finely, pagination is also working, just facing issue with filtering data in my ng2-smart-table.

how could you resolve it pleasae ?

SkanderLassoued09 avatar Oct 12 '22 13:10 SkanderLassoued09