ng2-smart-table
ng2-smart-table copied to clipboard
One million records
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
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?
I notice that "Local data source (Server/API DataSource is on its way)" in the wiki, is there any timeline of this feature?
+1
+1
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.
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.
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:
- 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.
- 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 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.
+1 for headers support, it would be very helpful
@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 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
@DeveBj You need to add
import {ApiService} from '...';
and
constructor(private api:ApiService) {
super(null);
}
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 Were you able to do that? Can you please share an example.
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.
did anyone got the solution??
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.)
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;
}
}
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.
Anyone here could tell me how can I make pagination using ng2 smart table and graphql ?
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 ?