Skip to content

Commit

Permalink
Resolved #329 - Tabulator - Server-Side (Remote) Pagination (#434)
Browse files Browse the repository at this point in the history
* Resolved #329 - Tabulator - Server-Side (Remote) Pagination

* Resolved #329 - Tabulator - Server-Side (Remote) Pagination - support promises and server-side filtering and sorting

* Update src/tables/table.ts

Co-authored-by: RomanTsukanov <RomanTsukanov@users.noreply.github.com>

* Update src/tables/table.ts

Co-authored-by: RomanTsukanov <RomanTsukanov@users.noreply.github.com>

* Update src/tables/table.ts

Co-authored-by: RomanTsukanov <RomanTsukanov@users.noreply.github.com>

* Update src/tables/table.ts

Co-authored-by: RomanTsukanov <RomanTsukanov@users.noreply.github.com>

* Update src/tables/table.ts

Co-authored-by: RomanTsukanov <RomanTsukanov@users.noreply.github.com>

* Work for #329 - Tabulator - Server-Side (Remote) Pagination - Updated API

* Work for #329 - Tabulator - Server-Side (Remote) Pagination - Fixed typings

---------

Co-authored-by: tsv2013 <tsv2013@noreply.github.com>
Co-authored-by: RomanTsukanov <RomanTsukanov@users.noreply.github.com>
  • Loading branch information
3 people authored May 21, 2024
1 parent d05cdfb commit a05429c
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 18 deletions.
26 changes: 26 additions & 0 deletions examples/tabulator-remote.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>

<head>
<title>Tabulator Example</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />

<link rel="stylesheet" type="text/css" href="../node_modules/tabulator-tables/dist/css/tabulator.css" />
<link rel="stylesheet" type="text/css" href="../packages/survey.analytics.tabulator.css" />
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"></script>
<script type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.0.10/jspdf.plugin.autotable.min.js"></script>
<script type="text/javascript" src="https://oss.sheetjs.com/sheetjs/xlsx.full.min.js"></script>
<script src="../node_modules/tabulator-tables/dist/js/tabulator.js"></script>
<script src="../node_modules/survey-core/survey.core.js"></script>
<script src="../node_modules/survey-core/survey.i18n.js"></script>
<script src="../packages/survey.analytics.tabulator.js"></script>
</head>

<body>
<div id="tabulatorContainer"></div>
<script src="./data_multi_lang.js"></script>
<script src="./tabulator-remote.js"></script>
</body>

</html>
43 changes: 43 additions & 0 deletions examples/tabulator-remote.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
var survey = new Survey.SurveyModel(json);

var normalizedData = data.map(function (item) {
survey.getAllQuestions().forEach(function (q) {
if (!item[q.name]) {
item[q.name] = "";
}
});
return item;
});

SurveyAnalyticsTabulator.Table.showFilesAsImages = true;

// function getPaginatedData({ offset, limit, filter, sort, callback }) {
// console.log(JSON.stringify(filter));
// console.log(JSON.stringify(sort));
// setTimeout(() => {
// callback({ data: normalizedData.slice(offset, offset + limit), totalCount: normalizedData.length });
// }, 1000);
// }

// function getPaginatedData({ offset, limit, filter, sort}) {
// const url = "http://www.example.com/";
// const reqBody = { offset, limit, filter, sort };
// return fetch(url, { body: reqBody });
// }

function getPaginatedData({ offset, limit, filter, sort }) {
console.log(JSON.stringify(filter));
console.log(JSON.stringify(sort));
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ data: normalizedData.slice(offset, offset + limit), totalCount: normalizedData.length });
}, 1000);
});
}

var surveyAnalyticsTabulator = new SurveyAnalyticsTabulator.Tabulator(
survey,
getPaginatedData
);

surveyAnalyticsTabulator.render("tabulatorContainer");
42 changes: 27 additions & 15 deletions src/tables/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ export interface ITableOptions {
}) => void;
}

export type TabulatorFilter = { field: string, type: string, value: any };
export type TabulatorSortOrder = { field: string, direction: undefined | "asc" | "desc" };
export type GetDataUsingCallbackFn = (params: { filter?: Array<TabulatorFilter>, sort?: Array<TabulatorSortOrder>, offset?: number, limit?: number, callback?: (response: { data: Array<Object>, totalCount: number, error?: any }) => void }) => void;
export type GetDataUsingPromiseFn = (params: { filter?: Array<TabulatorFilter>, sort?: Array<TabulatorSortOrder>, offset?: number, limit?: number }) => Promise<{ data: Array<Object>, totalCount: number, error?: any }>;
export type GetDataFn = GetDataUsingCallbackFn | GetDataUsingPromiseFn;
// export type GetDataFn = (params: { filter?: any, limit?: number, offset?: number, callback?: (response: { data: Array<Object>, total: number, error?: any }) => void }) => Promise<{ data: Array<Object>, total: number, error?: any }> | void;

export class TableEvent extends EventBase<Table> {}

export abstract class Table {
Expand All @@ -44,7 +51,7 @@ export abstract class Table {
protected _columns: Array<IColumn>;
constructor(
protected _survey: SurveyModel,
protected data: Array<Object>,
protected data: Array<Object> | GetDataFn,
protected _options: ITableOptions = {},
protected _columnsData: Array<IColumnData> = []
) {
Expand Down Expand Up @@ -187,21 +194,26 @@ export abstract class Table {
}
public get isInitTableDataProcessing(): boolean { return this.isInitTableDataProcessingValue; }
private isInitTableDataProcessingValue: boolean;
protected initTableData(data: Array<any>) {
this.isInitTableDataProcessingValue = true;
this.tableData = (data || []).map((item) => {
var dataItem: any = {};
this._survey.data = item;
this._columns.forEach((column) => {
const opt = column.getCellData(this, item);
if (typeof this._options.onGetQuestionValue === "function") {
this._options.onGetQuestionValue(opt);
}
dataItem[column.name] = opt.displayValue;
});

return dataItem;
protected processLoadedDataItem(item: any): any {
var dataItem: any = {};
this._survey.data = item;
this._columns.forEach((column) => {
const opt = column.getCellData(this, item);
if (typeof this._options.onGetQuestionValue === "function") {
this._options.onGetQuestionValue(opt);
}
dataItem[column.name] = opt.displayValue;
});

return dataItem;
}
protected initTableData(data: Array<any> | GetDataFn): void {
if(!Array.isArray(data)) {
this.tableData = undefined;
return;
}
this.isInitTableDataProcessingValue = true;
this.tableData = (data || []).map((item) => this.processLoadedDataItem(item));
this.isInitTableDataProcessingValue = false;
}

Expand Down
36 changes: 33 additions & 3 deletions src/tables/tabulator.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ITableOptions, Table, TableRow } from "./table";
import { GetDataFn, ITableOptions, Table, TableRow } from "./table";
import { SurveyModel } from "survey-core";
import { ColumnDataType, IColumnData, QuestionLocation } from "./config";
import { DocumentHelper } from "../utils";
Expand Down Expand Up @@ -88,7 +88,7 @@ export class Tabulator extends Table {

constructor(
survey: SurveyModel,
data: Array<Object>,
data: Array<Object> | GetDataFn,
options?: ITabulatorOptions,
_columnsData: Array<IColumnData> = []
) {
Expand Down Expand Up @@ -127,7 +127,7 @@ export class Tabulator extends Table {
targetNode.appendChild(header);
targetNode.appendChild(this.tableContainer);

var config = {};
var config: any = {};
Object.assign(
config,
{
Expand All @@ -151,6 +151,36 @@ export class Tabulator extends Table {
},
this._options.tabulatorOptions
);
if(data === undefined && typeof this.data === "function") {
delete config.data;
config.pagination = "remote";
config.ajaxFiltering = true; // Tabulator v4.8
config.filterMode = "remote"; // Tabulator v6.2
config.ajaxSorting = true; // Tabulator v4.8
config.sortMode = "remote"; // Tabulator v6.2
config.ajaxURL = "function",
config.ajaxRequestFunc = (url, config, params) => {
return new Promise<{ data: Array<Object>, last_page: number }>((resolve, reject) => {
const dataLoadingCallback = (loadedData: { data: Array<Object>, totalCount: number, error?: any }) => {
if(!loadedData.error && Array.isArray(loadedData.data)) {
resolve({ data: loadedData.data.map(item => this.processLoadedDataItem(item)), last_page: Math.ceil(loadedData.totalCount / params.size) });
} else {
reject();
}
};
const dataLoadingPromise = (this.data as GetDataFn)({
offset: (params.page - 1) * params.size,
limit: params.size,
filter: this.tabulatorTables?.getFilters(),
sort: this.tabulatorTables?.getSorters().map(s => ({ field: s.field, dir: s.dir })),
callback: dataLoadingCallback
});
if(dataLoadingPromise) {
dataLoadingPromise.then(dataLoadingCallback);
}
});
};
}

this.tabulatorTables = new TabulatorTables(this.tableContainer, config);

Expand Down

0 comments on commit a05429c

Please sign in to comment.