Display dynamic data

0
Hello, I am reading data from an external database, and the table that I need to display is a vertical table, with a structure like the one below: Field_Name, Field_Value, File_Id (I have files that store orders information). Example: Field_Name | Field_Value | File_IdOrder No. | 12345 | 1Item No. | 00000 | 1Order No. |67890 | 1....Each file can contain a different set of fields, so the list of Field_Name values is not fixed.On my page, I have a clickable Datagrid2 that displays the file name and File_Id. When a user selects a row, I want to display the extracted data for that specific file.The challenge is that I would like to present the data in a horizontal/tabular format, so instead of the example above, it needs to be like:Order No. | Item No. | ......12345 | 00000 67890 | ....... but because the columns are dynamic and may vary from one file to another, a standard Datagrid2 does not seem suitable since it requires a predefined set of columns.Has anyone encountered a similar scenario? Is there a recommended approach or workaround in Mendix for displaying data dynamically when the available fields differ between records?Any suggestions would be greatly appreciated.
asked
3 answers
1

Hey ,


One possible approach is to use a custom widget or a dynamically generated layout instead of Datagrid2, since Datagrid2 requires predefined columns. You can retrieve the data for the selected File_Id, group the records based on the required structure, and dynamically generate the column headers from the distinct Field_Name values. The corresponding Field_Value can then be displayed under each column. This would require some custom implementation, as the standard Mendix widgets do not directly support dynamic columns based on the data.


Regards
Reemali

answered
1

Hi Alexia,


This is a case where I would avoid trying to make the Data Grid 2 columns dynamic. Data Grid 2 requires the columns to be defined in the page configuration. Although columns can be conditionally shown/hidden using the Visible expression, it does not create new columns dynamically at runtime.

In your case, the data is essentially an EAV/key-value structure:

File_Id | Field_Name | Field_Value
----------------------------------
1       | Order No.  | 12345
1       | Item No.   | 00000
1       | Customer   | ABC
2       | Order No.  | 67890
2       | Item No.   | 11111
2       | Supplier   | XYZ

You want to pivot that into:

Order No. | Item No. | Customer | Supplier
------------------------------------------
12345     | 00000    | ABC      |
67890     | 11111    |          | XYZ

The problem is that Order No., Item No., Customer, Supplier, etc. are not known at design time.

If the set of fields is known

If there is actually a finite set of possible fields, I would model them as attributes on a view/helper entity and configure those as normal Data Grid 2 columns.

For example:

DynamicFileRow
----------------
OrderNo
ItemNo
Customer
Supplier

Then Data Grid 2 works normally.

You can also use the Visible expression to hide columns that are not applicable for the selected file. This is supported by Data Grid 2.


If the fields are genuinely dynamic

If a file can contain completely different field names and there is no fixed maximum set, I would not use Data Grid 2 for the final presentation.


Instead, I would use a custom table/grid component where the headers and cells are generated from the runtime data.


The structure would be:

Selected File
     ↓
Retrieve Field_Name / Field_Value records
     ↓
Build distinct Field_Name list
     ↓
Build rows grouped by the business record
     ↓
Custom dynamic table
     ↓
Dynamic headers + dynamic cell values

For example, the UI component receives something like:

Columns:
[
  "Order No.",
  "Item No.",
  "Customer",
  "Supplier"
]

Rows:
[
  ["12345", "00000", "ABC", ""],
  ["67890", "11111", "", "XYZ"]
]

and renders the table dynamically.


I would keep the original Field_Name / Field_Value / File_Id structure in the Mendix domain model rather than creating database attributes dynamically. Mendix attributes and Data Grid 2 columns are design-time model elements, so creating a new database attribute/column for every new field is not a suitable runtime solution.


If you need the data to remain completely generic, another option is to create a view entity/OQL-based read model for the required transformation. View entities can expose dynamically queried data, but they still do not make Data Grid 2 columns dynamic; the grid columns themselves remain configured in the page.


So I would choose between these two approaches:

Known / controlled set of fields
        ↓
Helper/View entity
        ↓
Data Grid 2

or

Unknown fields at runtime
        ↓
Field_Name / Field_Value model
        ↓
Pivot/group the data
        ↓
Custom dynamic table widget

For your example, because each file can contain a different set of fields, I would go with the second approach rather than trying to work around Data Grid 2.


Hope this helps.

answered
0

JavaScript Snippet

Instead of forcing Data Grid 2 to have dynamic columns, use a Pluggable Widget with JavaScript (or an HTML/JavaScript snippet widget from the Marketplace).
Use a microflow to retrieve the rows (Name, Value, Id), store them on a dataview.
Then use a snipplet that dynamically builds HTML <table>, <thead> and <tbody> elements at runtime.

Example JSON:

[
  { "Order": "12345", "Item": "00000", "Name": "ABC" },
  { "Order": "67890", "Item": "11111", "Name": "XYZ" }
]


Javascript code

contextObject.get('YourModuleName.HelperEntity.DynamicJSONDataView'))
const rawData = contextObject ? contextObject.get("DynamicJSONDataView") : "[]";

let rows = [];
try {
    rows = JSON.parse(rawData);
} catch (e) {
    console.error("Invalid JSON data:", e);
}

const container = document.getElementById("dynamic-table-container");
if (!container) return;

if (!rows || rows.length === 0) {
    container.innerHTML = "<p>No data available for this file.</p>";
    return;
}

const columns = [...new Set(rows.flatMap(row => Object.keys(row)))];

let html = '<div class="table-responsive"><table class="table table-striped table-bordered"><thead><tr>';
columns.forEach(col => {
    html += `<th>${parseHtml(col)}</th>`;
});
html += '</tr></thead><tbody>';

rows.forEach(row => {
    html += '<tr>';
    columns.forEach(col => {
        html += `<td>${parseHtml(row[col] || '')}</td>`;
    });
    html += '</tr>';
});
html += '</tbody></table></div>';

container.innerHTML = html;

function parseHtml(str) {
    return String(str)
        .replace(/&/g, "&")
        .replace(/</g, "<")
        .replace(/>/g, ">")
        .replace(/"/g, """)
        .replace(/'/g, "'");
}

Put this at the end of the snipplet <div id="dynamic-table-container"></div>


Regards!

answered