Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Constructing Dynamic Column Layouts in jQuery EasyUI Datagrid

Tech May 9 3

In enterprise applications, user interfaces often require flexible layouts that adapt based on specific business contexts rather than remaining static. A common scenario involves configuring a DataGrid’s visible columns dynamically based on backend settings. This approach ensures that sensitive or irrelevant fields are hidden from users unless specific conditions are met.

The following implementation demonstrates how to fetch column configuration definitions via an API endpoint, merge them with a static base schema, and render the resulting layout efficiently. Key improvements over traditional methods include avoiding synchronous AJAX requests and utilizing modern JavaScript patterns for clearer execution flow.

Fetching Configuration Schema

Instead of hardcoding column structures, we define a dedicated service function responsible for retrieving the necessary metadata. This function accepts context parameters and returns a list of configuration objects compatible with the Datagrid plugin.

// Retrieve dynamic column definitions from the server
function fetchColumnConfiguration(params) {
    const configEndpoint = '/api/CVRM/DynamicColumns';
    
    return new Promise((resolve, reject) => {
        $.ajax({
            url: `${configEndpoint}?id=${params.masterId}&quoteType=${params.type}&bizType=${params.businessCategory}`,
            method: 'GET',
            dataType: 'json'
        })
        .done((response) => {
            const formattedColumns = [];
            
            if (Array.isArray(response) && response.length > 0) {
                response.forEach((colDefinition, index) => {
                    // Map API response to grid column properties
                    formattedColumns.push({
                        field: `ID_${colDefinition.ColumnID}`,
                        title: colDefinition.ColumnTitle,
                        width: 100,
                        editor: {
                            type: 'numberbox'
                        }
                    });
                });
            }
            resolve(formattedColumns);
        })
        .fail((jqXHR, status) => {
            console.error('Failed to load column schema:', status);
            reject(new Error(status));
        });
    });
}

Merging and Initializing the Grid

Once the dynamic schema is obtained, its concatenated with pre-defined columns required for core functionality, such as checkboxes or system tracking identifiers. This combined array is then passed to the initialization method. Note the separation of concerns between data fetching and UI rendering.

async function initializeShippingRateGrid(rowId) {
    const containerSelector = '#gridTableFRT';
    
    // 1. Define immutable structural columns
    const baseLayout = [
        { checkbox: true },
        { field: 'FRTID', title: 'Identifier', align: 'center', width: 60, hidden: true },
        { field: 'PQID', title: 'Quote Reference', align: 'center', width: 60, hidden: true },
        { field: 'SourceLocID', title: 'Origin Location', align: 'center', width: 60, hidden: true, editor: { type: 'text' } },
        { field: 'DestLocID', title: 'Destination Location', align: 'center', width: 60, hidden: true, editor: { type: 'text' } }
    ];

    try {
        // 2. Retrieve dynamic columns asynchronously
        const customColumns = await fetchColumnConfiguration({
            masterId: 'MASTER_666666',
            type: 'ProcurementPrice',
            businessCategory: 'Vehicle'
        });

        // 3. Combine static and dynamic schemas
        const finalColumns = [
            ...baseLayout,
            {
                field: 'SourceName',
                title: 'Departure Zone',
                width: 210,
                align: 'center',
                editor: {
                    type: 'combogrid',
                    options: {
                        panelWidth: 210,
                        mode: 'remote',
                        idField: 'AreaName',
                        textField: 'AreaName',
                        url: '/Master/Area/List',
                        columns: [[
                            { field: 'AreaID', title: 'ID', width: 60, hidden: true },
                            { field: 'AreaName', title: 'Zone Name', width: 200 }
                        ]]
                    }
                }
            },
            {
                field: 'DestName',
                title: 'Arrival Zone',
                width: 210,
                align: 'center',
                editor: {
                    type: 'combogrid',
                    options: {
                        panelWidth: 210,
                        mode: 'remote',
                        idField: 'AreaName',
                        textField: 'AreaName',
                        url: '/Master/Area/List',
                        columns: [[
                            { field: 'AreaID', title: 'ID', width: 60, hidden: true },
                            { field: 'AreaName', title: 'Drop-off Zone', width: 200 }
                        ]]
                    }
                }
            },
            { field: 'ContainerClass', title: 'Container Type', width: 110, align: 'center', editor: { type: 'combogrid', options: { url: '/Master/Container/List' } } },
            { field: 'GoodsClassification', title: 'Item Category', width: 100, align: 'center', editor: { type: 'combobox', options: { url: '/Sys/Code/Goods' } } },
            { field: 'MinCharge', title: 'Min Rate (CNY)', width: 120, align: 'left', editor: { type: 'numberbox', options: { precision: 2, required: true } } },
            { field: 'LeadTimeDays', title: 'Duration', width: 150, align: 'center', editor: { type: 'numberbox' } },
            { field: 'TotalDistanceKm', title: 'Mileage', width: 150, align: 'center', editor: { type: 'numberbox', options: { required: true } } },
            { field: 'HazardLevel', title: 'DG Class', width: 100, align: 'left', editor: { type: 'combobox', options: { url: '/Sys/Code/Hazards' } } },
            { field: 'ProductDescription', title: 'Description', width: 150, align: 'left', editor: { type: 'combogrid', options: { url: '/Master/Product/List' } } },
            { field: 'UNCode', title: 'UN Code', width: 120, align: 'left', editor: { type: 'text' } },
            { field: 'Remarks', title: 'Notes', width: 200, align: 'left', editor: { type: 'text' } }
        ];

        // Append dynamic columns retrieved from API
        if (customColumns && customColumns.length > 0) {
            finalColumns.push(...customColumns);
        }

        // 4. Initialize the Datagrid with merged configuration
        $(containerSelector).datagrid({
            pageSize: 50,
            pageList: [50, 100, 200],
            singleSelect: false,
            sortable: true,
            url: '/api/CVRM/QuoteDetails',
            queryParams: { refKey: rowId },
            fitColumns: true,
            columns: [finalColumns],
            onLoadSuccess: function () {
                $(containerSelector).datagrid('resize');
            }
        });

        // Attach editing model if required
        new com.editGridViewModel($(containerSelector));

        // Adjust grid dimensions to viewport
        $(containerSelector).datagrid('resize', {
            width: $('.gridPanel').width(),
            height: $(window).height() - $('.gridPanel').offset().top - 260
        });

    } catch (error) {
        console.warn('Grid initialization halted due to schema error:', error);
    }
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.