How to Conditionally Remove Rows from a Child Table in Frappe
Remove table rowLearn to write a Frappe Client Script to programmatically remove rows from a child table based on field values using grid.grid_rows[i].remove().
In Frappe and ERPNext, managing child table data dynamically is a common requirement for creating interactive and user-friendly forms. This code snippet demonstrates a powerful technique for removing rows from a child table based on specific conditions, triggered by a custom button.
This client-side script is particularly useful for cleaning up data, filtering entries based on a parent document's state, or allowing users to perform bulk actions on child table rows without needing to manually delete them one by one.
1 // On click event of remove_btn 2
3 frappe.ui.form.on("Quotation", "remove_btn", function(frm) { 4 var tbl = frm.doc.items || []; 5 var i = tbl.length; 6 while (i--){ 7 if(frm.doc.select_item){ 8 if(tbl[i].main_item == frm.doc.select_item){ 9 frm.get_field("items").grid.grid_rows[i].remove(); 10 } 11 } 12 else { 13 if(tbl[i].main_item){ 14 frm.get_field("items").grid.grid_rows[i].remove(); 15 } 16 } 17 } 18 cur_frm.refresh(); 19
20 });
Understanding This Code
What It Does
This script iterates through all rows in the 'items' child table and removes those that match a specific condition related to a value in the parent DocType.
When To Use
Use this script when you need to provide users with a way to perform a bulk removal of child table rows based on criteria defined in the main form, such as filtering by a selected item category.
Prerequisites
- •A parent DocType (e.g., 'Quotation') with a child table (e.g., 'items').
- •A custom button with fieldname 'remove_btn' on the parent DocType.
- •A field in the parent form (e.g., 'select_item') to use as a filter condition.
Key Concepts
Important ideas to understand in this code
frappe.ui.form.on
A client-side API used to attach event handlers to form events. In this case, it listens for a click on the field (button) named 'remove_btn' on the 'Quotation' form.
Learn moreChild Table Grid API
The expression 'frm.get_field("items").grid.grid_rows' accesses the live grid rows of the child table. The .remove() method on a specific grid row object deletes it from both the UI and the form's data.
Learn moreIterating Backwards with while(i--)
When removing items from an array or collection you are iterating over, it's crucial to loop backward. This prevents issues with shifting indices that would cause the loop to skip items if you were iterating forward.
Learn morecur_frm.refresh()
After modifying the grid, calling cur_frm.refresh() is essential. It redraws the form, including the child table, ensuring that UI calculations, totals, and layout are updated correctly.
Learn moreStep-by-Step Tutorial
Follow along to understand how this code works
Add a Custom Button and Filter Field
In your ERPNext instance, go to 'Customize Form' and select the 'Quotation' DocType. Add a new field of type 'Button' and set its 'Fieldname' to 'remove_btn'. Add another field (e.g., a Link field named 'select_item') that will be used for filtering.
// No code needed for this step. Use the Form Customization UI.Create a New Client Script
Navigate to 'Client Script' from the Awesome Bar. Click 'New', select 'Quotation' as the DocType, and save the script.
// No code needed for this step. Use the Client Script creation UI.Implement the Row Removal Logic
Copy and paste the provided JavaScript code into the script editor. This code binds the row removal logic to the click event of your new button.
frappe.ui.form.on("Quotation", "remove_btn", function(frm) {
var tbl = frm.doc.items || [];
var i = tbl.length;
while (i--){
if(frm.doc.select_item){
if(tbl[i].main_item == frm.doc.select_item){
frm.get_field("items").grid.grid_rows[i].remove();
}
}
else {
// If no item is selected, remove all rows with a main_item
if(tbl[i].main_item){
frm.get_field("items").grid.grid_rows[i].remove();
}
}
}
cur_frm.refresh();
});Test the Functionality
Open an existing Quotation or create a new one. Add several items to the 'items' table. Select a specific item in the 'select_item' field and click your 'Remove' button. Only the matching rows should be deleted from the child table.
// No code for this step. Test the functionality within a Quotation form.Common Issues & Solutions
Troubleshoot problems you might encounter