Trigger Event on Deletion of Grid Row in Frappe (Frappe v15)
Introduction: Why Grid Row Deletion Events Matter
Child tables are central to ERPNext workflows. From invoice items to BOM materials, grid rows store transactional data.
In Frappe Framework v15, triggering logic when a grid row is deleted allows developers to maintain data consistency, enforce business rules, and update dependent calculations in real time.
This guide explains how to reliably trigger an event when a grid row is deleted, using supported client-side APIs only.
What Is a Grid Row in Frappe?
A grid row represents a single record inside a Child Table DocType rendered in a parent form.
Examples include:
- Items in a Sales Invoice
- Materials in a BOM
- Tasks in a Project
Deleting a grid row removes that child document from the parent document’s children list.
Direct Answer: How Do You Trigger an Event When a Grid Row Is Deleted?
In Frappe v15, you trigger an event on grid row deletion by defining a client-side event handler on the Child Table DocType using the before_remove or after_remove event.
This approach is:
- Officially supported
- Upgrade-safe
- Consistent across Desk forms
Technical Prerequisites
Before implementing this logic, ensure:
- Frappe Framework Version 15
- A Parent DocType with a Child Table field
- A Child Table DocType
- Client scripting access (.js file or Custom Script)
Supported Events for Grid Row Deletion (v15)
| Event Name | Trigger Timing | Use Case |
| before_remove | Before row is deleted | Validation, warnings |
| after_remove | After row is deleted | Recalculation, sync |
✔ These events are verified in Frappe v15
✘ No deprecated or internal APIs used
Step-by-Step: Trigger Event on Grid Row Deletion
Step 1: Identify the Child Table DocType
Example:
- Parent DocType: Sales Order
- Child Table Field: items
- Child DocType: Sales Order Item
Your script must target Sales Order Item, not the parent.
Step 2: Add Client Script for the Child DocType
frappe.ui.form.on('Sales Order Item', {
before_remove: function(frm, cdt, cdn) {
frappe.msgprint(__('Item is about to be removed'));
}
});
What Happens Here?
- frm → Parent form object
- cdt → Child DocType
- cdn → Child document name
This fires immediately before deletion.
Trigger Logic After the Row Is Deleted
Example: Recalculate Totals After Row Removal
frappe.ui.form.on('Sales Order Item', {
after_remove: function(frm) {
frm.trigger('calculate_totals');
}
});
This ensures totals update automatically when an item is removed.
✔ Common ERPNext pattern
✔ Fully compatible with v15
Accessing Deleted Row Data (Before Removal)
You can still access the row data inside before_remove.
frappe.ui.form.on('Sales Order Item', {
before_remove: function(frm, cdt, cdn) {
let row = locals[cdt][cdn];
console.log(row.item_code, row.qty);
}
});
⚠ After removal, locals[cdt][cdn] is no longer available.
Conditional Deletion Control (Advanced Validation)
Example: Prevent Deletion Based on Condition
frappe.ui.form.on('Sales Order Item', {
before_remove: function(frm, cdt, cdn) {
let row = locals[cdt][cdn];
if (row.delivered_qty > 0) {
frappe.throw(__('You cannot remove a delivered item'));
}
}
});
This enforces business rules at UI level.
Real-World ERPNext Use Cases
Manufacturing
- Prevent removal of issued raw materials
- Recalculate BOM cost on item removal
Accounting
- Revalidate tax totals when invoice rows are deleted
Projects
- Update project progress when task rows are removed
Best Practices for Grid Row Deletion Handling
Technical Best Practices
- Use child DocType events only
- Prefer before_remove for validation
- Keep logic lightweight in client scripts
- Trigger recalculation via parent events
UX Best Practices
- Avoid unnecessary popups
- Use clear error messages
- Prevent deletion only when required
Common Mistakes to Avoid
| Mistake | Why It Fails |
| Binding delete logic on parent DocType | Event never fires |
| Using undocumented grid APIs | Breaks on upgrades |
| Heavy calculations in before_remove | UI lag |
| Assuming row data exists after removal | Data already deleted |
Troubleshooting Guide
Event Not Triggering?
Check:
- Correct Child DocType name
- Script loaded properly
- No JavaScript console errors
Validation Not Working?
Verify:
- frappe.throw() used inside before_remove
- No async code blocking execution
Integration Patterns
Grid row deletion events are commonly integrated with:
- Pricing engines
- Inventory validation
- External API sync
- Audit logging systems
They act as critical control points in ERP workflows.
Cross-References (Recommended)
- Client Script Events in Frappe
- Child Table Architecture in ERPNext
- Form Events vs Child Events
(Use internal goerpnext.com links for SEO strength)
Target Audience
- ERPNext Developers
- Frappe Framework Consultants
- ERP Functional + Technical Teams
- Customization Specialists
Industry Relevance
Grid row deletion handling is essential in:
- Manufacturing ERP
- Finance & Accounting
- Supply Chain Management
- Project-Based Industries
Summary: The Correct Way to Handle Grid Row Deletion
In Frappe Framework v15, the only supported and upgrade-safe way to trigger logic when a grid row is deleted is by using Child Table client-side events (before_remove and after_remove).
This approach ensures:
- Data integrity
- Clean UI behavior
- Long-term maintainability
References
- Official Frappe Guide: Trigger Event on Deletion of Grid Row
- Frappe Framework GitHub (Version 15)