Skip to content
Skip to the article
In Frappe: 20 articles
Frappe

Customizing Grid Columns for Child Tables

Force a specific set of grid columns per parent doctype when a child table is shared across several parents.

Updated
Tags
  • frappe
  • javascript
  • child-table
  • grid
Reading time
2 min

When a child table doctype is shared across multiple parent doctypes, the visible columns are typically controlled by user settings (per user/parent-doctype/child-doctype) or the child's in_list_view fields. To force a specific set of columns per parent doctype, override the grid's setup_user_defined_columns method in the parent form's on_setup hook.

Implementation

In the parent doctype's client script (e.g., sales_order.js), use the following pattern in the onload function:

onload: (frm) => {
    const child_grid = frm.fields_dict.child_fieldname.grid;  // Replace 'child_fieldname' with your table field name
    if (child_grid) {
        child_grid.df.on_setup = function(grid) {
            // Override the method to force custom columns, ignoring user settings
            grid.setup_user_defined_columns = function() {
                this.user_defined_columns = [
                    frappe.meta.get_docfield("Child Doctype", "fieldname1"),
                    frappe.meta.get_docfield("Child Doctype", "fieldname2"),
                    // Add more fields as needed
                ].map(df => {
                    df.in_list_view = 1;
                    df.columns = 1;  // Adjust column width (1-12 Bootstrap units)
                    return df;
                });
            };
        };
        // Refresh to apply the override
        child_grid.refresh();
    }
}

How It Works

  • The on_setup hook runs early in grid initialization.

  • Overriding setup_user_defined_columns ensures custom columns are used instead of default/user-defined ones.

  • This applies per grid instance (per parent form) without modifying core code.

  • Column widths are controlled via df.columns; the grid auto-adjusts if total width < 12.

Example

For a "BOM Item" child table in a "Sales Order" form, showing only "charge", "rate", "amount", and "charge_amount":

onload: (frm) => {
    const bom_items_grid = frm.fields_dict.items.grid;
    if (bom_items_grid) {
        bom_items_grid.df.on_setup = function(grid) {
            grid.setup_user_defined_columns = function() {
                this.user_defined_columns = [
                    frappe.meta.get_docfield("BOM Item", "charge"),
                    frappe.meta.get_docfield("BOM Item", "rate"),
                    frappe.meta.get_docfield("BOM Item", "amount"),
                    frappe.meta.get_docfield("BOM Item", "charge_amount")
                ].map(df => {
                    df.in_list_view = 1;
                    df.columns = 1;
                    return df;
                });
            };
        };
        bom_items_grid.refresh();
    }
}

Notes

  • Test by checking frm.fields_dict.child_fieldname.grid.user_defined_columns in the console.

  • For editable grids, ensure fields are appropriately visible.

  • If dynamic columns are needed based on form data, add conditional logic in the override.

This article is in the public domain (CC0 1.0), code samples included. Use it however helps you.