This example shows how to configure a server that can paginate, sort, filter, and otherwise process survey data and integrate this server with the SurveyJS Dashboard and Table View. The example uses a NodeJS server with a MongoDB database as a storage.
This demo must not be used as a real service as it doesn't cover such real-world survey service aspects as authentication, authorization, user management, access levels, and different security issues. These aspects are covered by backend-specific articles, forums, and documentation.
-
Install NodeJS and Docker Desktop on your machine.
-
Run the following commands:
git clone https://github.com/surveyjs/surveyjs-dashboard-table-view-nodejs-mongodb.git cd surveyjs-dashboard-table-view-nodejs-mongodb docker compose up -d
-
Open http://localhost:9080 in your web browser.
The Dashboard displays aggregated survey results as charts. By default, it loads all user responses from storage and processes them in the browser, which can significantly slow down loading. To improve performance, you can offload data aggregation to the server and return only the calculated statistics.
The Dashboard is created using the VisualizationPanel
constructor. Its second parameter is a callback function that the Dashboard calls whenever it needs to re-calculate data. This function receives an object with the following properties:
-
visualizer
:any
A single chart instance. Provides access to the survey question it visualizes. -
filter
:Array<{ field: string, type: string, value: any }>
Filter conditions that should be applied to the dataset. The filter format is based on Tabulator filters.
On the server, use these parameters to build aggregation pipelines and apply them to your dataset. The raw results may not match the Dashboard's expected format, so you'll need to transform the data before returning it.
For a complete example, see the retrieveSummary
function, which demonstrates how the server should handle load parameters and return processed results.
Table View displays unaggregated user responses in a table. Without server-side data processing, the Table View may take more time to launch, because it loads all user responses from a storage in one batch and processes them in the user's browser. To shorten the loading time, you can delegate sorting and filtering to the server and implement data pagination to load data in small batches.
The Table View is instantiated using the Tabulator
constructor, which accepts a function as a second parameter. This function is called each time the Table View requests the next batch of user responses. Its argument is an object with the following properties:
-
offset
:number
The number of records to skip from the beginning of the dataset. Used to implement data pagination. -
limit
:number
The number of records to load in the current batch. Used to implement data pagination. -
filter
:Array<{ field: string, type: string, value: any }>
Filter conditions that should be applied to the dataset. Refer to the Tabulator documentation for information on available filters. -
sort
:{ field: string, direction: undefined | "asc" | "desc" }
Sort order settings that should be applied to the dataset. -
callback
:(response: { data: Array<Object>, totalCount: number, error?: any }) => void })
A callback used to return the processed dataset. Instead of using the callback, the function can return a Promise.
Pass these load parameters in a server request. The server should apply them to the dataset and return processed data back to the client in an object with the following structure: { data: Array<Object>, totalCount: number, error?: any }
. Refer to the getObjectsPaginated
function implementation for an example of how the server should handle the load parameters.