Flexmonster Software License Agreement (“Agreement”) has been revised and is effective as of January 8, 2025.
The following modifications were made:
The modified version of Agreement is available here.
Downloading, installing, and/or continuing to use Flexmonster Software after January 8, 2025, constitutes Licensee’s acceptance of the terms and conditions of the modified version of Agreement. If Licensee does not agree to any of these terms and conditions, they must cease using Flexmonster Software and must not download, install, use, access, or continue to access Flexmonster Software. By continuing to use Flexmonster Software or renewing the license or maintenance after the effective date of these modifications to Agreement, Licensee accepts and agrees to be bound by the terms and conditions of the modified Agreement.
This guide describes how to create a custom UI control or view if Flexmonster does not provide the needed UI functionality. For example, you can create a custom filter view or a report picker.
You can also add custom functionality to the Toolbar and the context menu. For more details, refer to the Customizing the Toolbar and Customizing the context menu guides.
To see different examples of custom controls and views, visit our Examples page.
Step 1. Сreate an HTML structure to represent your control, such as a pop-up window, container, dropdown, button, etc.
Step 2. Use the Flexmonster API getter methods to retrieve the component’s current state. For example:
See the full list of Flexmonster API calls.
Step 3. Implement your custom functionality. If you need to track Flexmonster’s state and user actions, use Flexmonster events.
Step 4. Apply changes to the component using Flexmonster API setter methods (e.g., setReport() or runQuery() to set the slice). See the full list of Flexmonster API calls.
In this example, we create a custom report picker and a layout picker.
Step 1. Prepare the necessary reports: you can configure them via the UI. Then, save the reports (e.g., as a variable in code or as a file on the server). In our case, we define reports as a set of functions that return ReportObject:
function happinessReport() {
return {
dataSource: {
type: "csv",
filename: "https://cdn.flexmonster.com/data/happiness.csv",
},
slice: {
// Slice configs
},
options: {
// Options configs
},
// Other configs
};
}
Step 2. Create an HTML element that will be used as a picker (e.g., a set of buttons or a dropdown menu). In our example, we create two sets of buttons. The first set will be used to choose the report, and the second one for switching layouts.
Step 3. For the first set of buttons, implement a function that will switch the reports on the grid using the setReport() API call. If you store reports on the server, you can use the load() method.
Check out an example:
function connectTo(data) {
let report = "";
switch (data) {
case "happiness":
report = happinessReport();
break;
// Other cases
}
pivot.setReport(report);
}
Step 4. For the second set of buttons, create a function that changes the layout. Use the getOptions(), setOptions(), and refresh() API calls:
function changeView(view) {
viewType = view;
let options = pivot.getOptions();
switch (view) {
case "flat":
options.viewType = "grid";
options.grid.type = "flat";
break;
case "pivot":
options.viewType = "grid";
options.grid.type = "compact";
break;
case "charts":
options.viewType = "charts";
break;
}
pivot.setOptions(options);
pivot.refresh();
}
You can also explore an example of a report picker implemented as a dropdown menu and integrated into the Toolbar Live example.
This example describes how to create the Options pop-up window with custom functionality.
Step 1. Create an HTML element that will represent your custom Options pop-up window. Add controls for selecting the new option values, e.g., dropdowns.
Step 2. Create a function that opens the pop-up window. In this function, set the current option values in the UI control using the getOptions() API call. Your code should look similar to the following:
function showOptionsPopup() {
const popup = document.querySelector("#custom-options-popup");
const popupOverlay = document.querySelector("#popupOverlay");
// Get current Flexmonster options
const options = pivot.getOptions().grid;
// Set current values to the select elements
document.getElementById("custom-options-grand-totals-select").value = options.showGrandTotals ?? "on";
document.getElementById("custom-options-subtotals-select").value = options.showTotals ?? "on";
document.getElementById("custom-options-layout-select").value = options.type ?? "compact";
popup.classList.remove("hideCustomPopup");
popupOverlay.classList.remove("hideCustomPopup");
popupOverlay.onclick = closeOptionsPopup;
}
Step 3. Add a function that closes the pop-up window.
Step 4. Implement a function that applies the new options using the getOptions()
and setOptions() API calls. Use refresh() to update the grid with the new options. You can structure your code as follows:
function submitOptions() {
const grandTotalsSelect = document.getElementById("custom-options-grand-totals-select");
const subtotalsSelect = document.getElementById("custom-options-subtotals-select");
const layoutSelect = document.getElementById("custom-options-layout-select");
// Get the selected values
const grandTotalsValue = grandTotalsSelect.value;
const subtotalsValue = subtotalsSelect.value;
const layoutValue = layoutSelect.value;
let options = pivot.getOptions();
options.grid.type = layoutValue;
options.grid.showTotals = subtotalsValue;
options.grid.showGrandTotals = grandTotalsValue;
pivot.setOptions(options);
pivot.refresh();
closeOptionsPopup();
}
Step 5. (optional) To replace the default Options pop-up window with a custom one, handle the beforetoolbarcreated event.
In this example, we create a custom Field List where the user can edit only the Rows and Report Filters boxes:
Step 1. Create an HTML element for your custom Field List. In this element, create three <div>
elements, which will represent:
We will fill these elements with fields in the following steps.
Step 2. Implement a function that returns fields that are not currently used in the pivot table. These fields will be rendered in the Available fields box:
function getAvailableFields() {
// Get all fields
const allFields = pivot.getAllHierarchies();
// Get fields that are already present in the slice
const columns = pivot.getColumns().map((col) => col.uniqueName);
const measures = pivot.getMeasures().map((measure) => measure.uniqueName);
const rows = pivot.getRows().map((row) => row.uniqueName);
const filters = pivot.getReportFilters().map((f) => f.uniqueName);
// Filter out fields that are already used
return allFields.filter(
(field) =>
!columns.includes(field.uniqueName) &&
!measures.includes(field.uniqueName) &&
!rows.includes(field.uniqueName) &&
!filters.includes(field.uniqueName)
);
}
This function uses the following API calls: getAllHierarchies(), getRows(), getColumns(), getMeasures(), and getReportFilters().
Step 3. Create a function (e.g., openFieldList()
) that opens the Field List. In this function, get the fields that will be rendered:
function openFieldList() {
const availableFields = getAvailableFields();
const currentRows = pivot.getRows();
const currentFilters = pivot.getReportFilters();
document.getElementById("field-list").style.display = "block";
backdrop.style.display = "block";
}
Step 4. Inside openFieldList()
, define a helper function that renders the fields:
function openFieldList() {
const availableFields = getAvailableFields();
const currentRows = pivot.getRows();
const currentFilters = pivot.getReportFilters();
const renderFields = (containerId, fields) => {
const container = document.getElementById(containerId);
const header = container.querySelector("h3")?.outerHTML || ""
container.innerHTML = header
fields.forEach((field) => {
const item = document.createElement("div");
item.className = "draggable-field";
item.draggable = true;
item.innerText = field.caption;
item.dataset.uniqueName = field.uniqueName;
container.appendChild(item);
});
};
renderFields("available-fields", availableFields);
renderFields("rows", currentRows);
renderFields("report-filters", currentFilters);
document.getElementById("field-list").style.display = "block";
backdrop.style.display = "block";
}
Step 5. Implement drag and drop. When the field is dropped into a certain box, save this field to the corresponding array. Also, remove the relocated field from the Available fields box.
Step 6. When the user clicks the APPLY button, call the runQuery() method to set a new report. Get the current columns and measures from the component so they remain unchanged:
function applySlice() {
const rows = [...document.getElementById("rows").children].map((el) => ({
uniqueName: el.dataset.uniqueName,
}))
const reportFilters = [...document.getElementById("report-filters").children].map(
(el) => ({
uniqueName: el.dataset.uniqueName,
}),
)
const columns = pivot.getColumns();
const measures = pivot.getMeasures();
pivot.runQuery({
rows,
reportFilters,
columns,
measures,
})
closeFieldList();
}