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.
On this page
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_setuphook runs early in grid initialization.Overriding
setup_user_defined_columnsensures 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_columnsin 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.