This guide will demonstrate how to implement the custom data source API protocol on your server so the server can send data to Flexmonster.
We will use our sample Node.js server as an example, but the instructions in the guide are relevant for any server technology and data source.
Your server must provide the custom data source API endpoints that handle POST requests from Flexmonster.
Flexmonster sends 4 types of requests:
Here is an example of creating the endpoints for the requests using Express.js:
const cube = require('express').Router(); cube.post("/handshake", async (req, res) => {}); cube.post("/fields", async (req, res) => {}); cube.post("/members", async (req, res) => {}); cube.post("/select", async (req, res) => {});
As you can see, the request's name corresponds to its endpoint. For example, all /select requests are sent to the /select
endpoint.
In the next steps, you will learn how to handle each request.
First, Flexmonster sends the /handshake request to establish communication with the server. The component includes its version in the request and expects a response with the custom data source API version implemented by the server.
In the response to the /handshake request, it is recommended to send the flexmonster.js
version used at the time of implementing the custom data source API. For example, if you handle the request while using Flexmonster version 2.9.80, specify 2.9.80
as the server’s custom data source API version.
Here is an example of how to handle the /handshake request:
cube.post("/handshake", async (req, res) => { try { res.json( { version: "<server_API_version>" } ); } catch (err) { handleError(err, res); } });
Read more details about the /handshake request in the documentation.
Flexmonster sends the /fields request to get information about the data structure, which includes:
"string"
, "number"
, and "date"
field types.Learn how to enable filters and aggregation functions on your server for the custom data source API.
Note Your server must support at least one aggregation for at least one field or field type so you can select a field as a measure.
Here is an example of handling the /fields request:
cube.post("/fields", async (req, res) => { try { const result = await getFields(req.body.index); res.json(result); } catch (err) { handleError(err, res); } });
The getFields
method must return the response to the /fields request. See how getFields
is implemented in the sample Node.js server.
Read more details about the /fields request in the documentation.
The /members request is sent to get members of fields selected for the slice.
Note The server should pass date members to Flexmonster as Unix timestamps in milliseconds. For example, "2016-02-07"
is 1454803200000
when converted to a Unix timestamp in milliseconds.
Here is an example of handling the /members request:
cube.post("/members", async (req, res) => { try { const result = await getMembers(req.body.index, req.body.field, req.body.page); res.json(result); } catch (err) { handleError(err, res); } });
The getMembers
method must return the response to the /members request. See how getMembers
is implemented in the sample Node.js server.
Read more details about the /members request in the documentation.
To get data, Flexmonster sends the /select request for the pivot table, the flat table, or the drill-through view based on the current view. The component will send the /select requests when you change the slice or switch between the views.
Here is an example of handling the /select requests:
cube.post("/select", async (req, res) => { try { const result = await getSelectResult(req.body.index, req.body.query, req.body.page); res.json(result); } catch (err) { handleError(err, res); } });
The structure of the req.body.query
property is different for the /select requests for the pivot table, for the flat table, and for the drill-through view. The getSelectResult
method must return the response to the corresponding /select request. See how getSelectResult
is implemented in the sample Node.js server.
Read more details about the /select requests for the pivot table, the flat table, and the drill-through view in the documentation.
By default, cross-domain requests are blocked on the server. If Flexmonster Pivot and your custom data source API server are running on different domains, enable CORS to allow requests from the component.
Here is how to enable CORS on a Node.js server using the cors package:
const express = require("express"); const cors = require("cors"); // Other imports const app = express(); app.use(cors()); // Other configurations
Testing your server allows you to ensure the custom data source API requests are handled as expected. You can use our test suite that covers basic use cases or create your own test suite.
Now you can connect Flexmonster to your server. In the report.dataSource, define the following properties:
const pivot = new Flexmonster({ container: "pivotContainer", componentFolder: "node_modules/flexmonster/", toolbar: true, report: { dataSource: { type: "api", // The base URL to your API endpoints url: "http://localhost:3400/api/cube", // Identifier of your dataset // Will be sent with every request index: "dataset-123" } } });
See the full list of Flexmonster properties used to connect to the custom data source API.
Now, if you open your page in a browser, you can start analyzing data in the pivot table.
If your data contains non-Latin characters, ensure you have set UTF-8 encoding for your data and page so the data is displayed correctly in the component.
You may be interested in the following articles: