Skip to main content

Using Table

Dynamically Modifying Table Columns

The Table API provides the updateComponentProps method, which can be used to modify any table properties, including the column definitions (columnDefs).

For example, after the table is rendered, clicking the "Add Column" button dynamically adds a new column 12/2/2024 to the table.

update-column-defs-run

The configuration in the designer is as follows:

update-column-defs-button update-column-defs-js

The JavaScript code for this example is as follows:

formApi.registerMethod('changeColumnDefs', () => {
const tableApi = formApi.getFieldApi('45cfdeaa-table');
const { columnDefs } = tableApi.getComponentProps();

const newColDef = {
colId: new Date().toLocaleDateString(),
field: new Date().toLocaleDateString(),
headerName: new Date().toLocaleDateString(),
};
const newColumnDefs = [...columnDefs, newColDef];

tableApi.updateComponentProps({
columnDefs: newColumnDefs,
});
});

Complex Table Column Definitions

Using the updateComponentProps method mentioned above, you can dynamically modify the column definitions to achieve complex table column definitions.complex-table-column-js complex-table-form-render

Complex table column definitions must be implemented using JavaScript code in the "JS Code" section. For more information, refer to the official ag-Grid documentation: https://www.ag-grid.com/javascript-data-grid/component-cell-renderer/.

The JavaScript code for this example is as follows:


formApi.on('ready', function () {
const tableApi = formApi.getFieldApi('test-table');
const { columnDefs } = tableApi.getComponentProps();
const additionalColumnDefs = [
{
headerName: 'Plain String',
field: 'code',
colId: 'code',
},
{
headerName: 'Two Lines Display',
field: 'name',
cellRenderer: BasicInfoRender,
},
{
headerName: 'Render Color',
field: 'colorSize',
cellRenderer: ColorSizeRender,
},
{
headerName: 'Text with Link',
field: 'order',
cellRenderer: OrderRender,
},
{
headerName: 'Table',
field: 'countDetail',
cellRenderer: CountDetailRender,
},
{
headerName: 'Open Modal',
field: 'openModal',
cellRenderer: OpenModalRender,
},
{
headerName: 'Header Spanning Columns',
colId: 'arrange',
field: 'arrange',
children: [
{
colId: 'color',
field: 'color',
headerName: 'Column One',
},
{
colId: 'number',
field: 'number',
headerName: 'Column Two',
},
],
},
];
const newColumnDefs = [...columnDefs, ...additionalColumnDefs];
tableApi.updateComponentProps({
rowHeight: 220,
columnDefs: newColumnDefs,
});
});

class BasicInfoRender {
eGui;

// Optional: Params for rendering. The same params that are passed to the cellRenderer function.
init(params) {
const { code, name } = params.data;
this.eGui = document.createElement('div');

this.eGui.innerHTML = `<div >
<span>Code: </span>
<span>${code}</span>
</div>
<div >
<span>Name: </span>
<span>${name}</span>
</div>
</div>`;
}

// Required: Return the DOM element of the component, this is what the grid puts into the cell
getGui() {
return this.eGui;
}

// Required: Get the cell to refresh.
refresh(params) {
return false;
}
}

class ColorSizeRender {
eGui;

generateTag(name) {
return `<span class="table-cell-tag">${name}</span>`;
}
// Optional: Params for rendering. The same params that are passed to the cellRenderer function.
init(params) {
const { color, size } = params.data;

this.eGui = document.createElement('div');
this.eGui.innerHTML = `<div ><div >
<span>Color: </span>
<span>${color
.map((item) => {
return this.generateTag(item);
})
.join(' ')}</span>
</div>
</div>`;
}

// Required: Return the DOM element of the component, this is what the grid puts into the cell
getGui() {
return this.eGui;
}

// Required: Get the cell to refresh.
refresh(params) {
return false;
}
}

class OrderRender {
eGui;

generateTag(name) {
return `<span class="table-cell-tag">${name}</span>`;
}
// Optional: Params for rendering. The same params that are passed to the cellRenderer function.
init(params) {
const { count, orderId } = params.data;

this.eGui = document.createElement('div');
this.eGui.innerHTML = `<div ><div >
<span>Count: </span>
<span>${count}</span>
</div>
<a href="/order${orderId}/view" class="table-cell-mock-button">View</a>
</div>`;
}

// Required: Return the DOM element of the component, this is what the grid puts into the cell
getGui() {
return this.eGui;
}

// Required: Get the cell to refresh.
refresh(params) {
return false;
}
}

class CountDetailRender {
eGui;

// Optional: Params for rendering. The same params that are passed to the cellRenderer function.
init(params) {
const { count, orderId } = params.data;

this.eGui = document.createElement('div');
this.eGui.innerHTML = `<table class="table-cell-table">
<tr>
<td>Color\Size</td>
<td>S</td>
<td>M</td>
<td>Total</td>
</tr>
<tr>
<td>Black</td>
<td>100</td>
<td>200</td>
<td>300</td>
</tr>
<tr>
<td>White</td>
<td>300</td>
<td>400</td>
<td>700</td>
</tr>
<tr>
<td>Total</td>
<td>400</td>
<td>600</td>
<td>1000</td>
</tr>
</table>`;
}

// Required: Return the DOM element of the component, this is what the grid puts into the cell
getGui() {
return this.eGui;
}

// Required: Get the cell to refresh.
refresh(params) {
return false;
}
}

class OpenModalRender {
eGui;
eButton;
eventListener;

generateTag(name) {
return `<span class="table-cell-tag">${name}</span>`;
}
// Optional: Params for rendering. The same params that are passed to the cellRenderer function.
init(params) {
const { count, orderId } = params.data;
this.eGui = document.createElement('div');
this.eButton = document.createElement('button');
this.eButton.className = 'btn-simple';
this.eButton.textContent = 'Edit';
this.eventListener = () => createModal();
this.eButton.addEventListener('click', this.eventListener);
this.eGui.appendChild(this.eButton);
}

// Required: Return the DOM element of the component, this is what the grid puts into the cell
getGui() {
return this.eGui;
}

// Required: Get the cell to refresh.
refresh() {
return true;
}

destroy() {
if (this.eButton) {
this.eButton.removeEventListener('click', this.eventListener);
}
}
}

function createModal() {
// Check if a modal already exists to avoid duplication
const existingModal = document.getElementById('modal');
if (existingModal) {
existingModal.style.display = 'block'; // If it exists, just show it
return;
}

// Create the HTML for the modal
const modalHTML = `
<div id="modal" class="modal">
<div class="modal-content">
<span class="close-btn">×</span>
<h2>Modal Title</h2>
<p>This is a modal with an embedded <iframe>.</p>
<iframe width="100%" height="300px" frameborder="0"></iframe>
</div>
</div>
`;

// Append the modal to the body
document.body.insertAdjacentHTML('beforeend', modalHTML);

// Get the newly created elements
const modal = document.getElementById('modal');
const closeBtn = modal.querySelector('.close-btn');
const iframe = modal.querySelector('iframe');

// Show the modal
modal.style.display = 'block';

// Set the iframe src (lazy loading)
iframe.src = 'https://baidu.com'; // This can be modified to another link

// Close the modal
closeBtn.addEventListener('click', () => {
modal.remove(); // Remove the modal
});

// Close the modal when clicking outside
modal.addEventListener('click', (event) => {
if (event.target === modal) {
modal.remove(); // Remove the modal
}
});
}

The CSS code in the "Frontend Configuration" for this example is as follows:

.table-cell-tag {
display: inline-block;
border: 1px solid grey;
padding: 4px;
line-height: 1.32;
background: #E6F4FF;
color: #1677FF;
}

.table-cell-mock-button {
display: inline-block;
padding: 5px;
line-height: 1.32;
background-color: #1677FF;
color: white;
text-decoration: none;
border-radius: 5px;
}

.table-cell-table {
border-collapse: collapse;
}

.table-cell-table td {
border: 1px solid;
width: 100px;
}

/* Modal container */
.modal {
display: none; /* Hidden by default */
position: fixed;
z-index: 1000; /* Ensure it is on top */
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.4); /* Semi-transparent background */
}

/* Modal content */
.modal-content {
background-color: #fefefe;
margin: 15% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
max-width: 600px; /* Adjust width to fit iframe */
position: relative;
}

/* Close button */
.close-btn {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
cursor: pointer;
}

.close-btn:hover {
color: #000;
}

/* iframe styling */
iframe {
border: none; /* Remove iframe border */
margin-top: 10px; /* Add some spacing */
width: 100%;
height: 300px;
}
The above operations also apply to the Editable Table component. :::

API

For the complete Table API reference, please refer to Table