We have updated Flexmonster Software License Agreement, effective as of September 30, 2024. Learn more about what’s changed.
All documentation
  • Introduction
  • Connecting to data source
    1. Supported data sources
    2. Connecting to other data sources
  • Browser compatibility
  • Documentation for older versions
  • Implementing the custom data source API on your server

    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.

    Prerequisites

    Step 1. Create the custom data source API endpoints

    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.

    Step 2. Handle the /handshake 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.

    Step 3. Handle the /fields request

    Flexmonster sends the /fields request to get information about the data structure, which includes:

    • Available fields. The server should include the following information about each field:
      • A field's name, type, caption, and folder.
      • Multilevel hierarchy configuration, if a field is a hierarchy level.
      • Aggregations and filters supported on the server for a field.
      • Interval (for a date field).
    • Aggregations and filters supported on the server for the "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.

    Step 4. Handle the /members request

    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.

    Step 5. Handle the /select requests

    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.

    Step 6. Enable cross-origin resource sharing (CORS)

    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

    Step 7. Test your custom data source API server

    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.

    Step 8. Connect Flexmonster to the server

    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.

    Display non-Latin characters correctly

    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.

    What's next?

    You may be interested in the following articles: