Skip to main content

Adding a Custom Button to a Frappe Form (Frappe v15)

Introduction: What Does Adding a Custom Button Mean in Frappe?

Adding a custom button in Frappe means extending a DocType form with a user-triggered action.
In Frappe Framework v15, custom buttons are added using client-side JavaScript and are commonly used to trigger workflows, call server-side methods, or navigate users to related records.
This guide explains how to add a custom button to a form in a technically correct and production-safe way.

When Should You Add a Custom Button?

Custom buttons are useful when you need:

  • Manual user actions beyond standard Save / Submit
  • Integration triggers (API calls, background jobs)
  • Navigation to related DocTypes
  • Controlled workflow steps without automation

Common ERPNext use cases

  • “Create Delivery Note” from Sales Order
  • “Generate Invoice” from custom DocType
  • “Sync with External System”

Technical Prerequisites

Before proceeding, ensure you have:

  • A running Frappe Framework v15 site
  • Access to the app’s public/js directory
  • A valid DocType to customize
  • Basic knowledge of JavaScript

How to Add a Custom Button to a Form in Frappe v15

Direct Answer (AEO-Optimized)

To add a custom button in Frappe v15, use the frm.add_custom_button() method inside the DocType’s client-side JavaScript file, typically within the refresh event.

Step-by-Step: Adding a Custom Button

Step 1: Locate or Create the Client Script File

For a DocType named Sales Order, the file path is:

your_app/your_app/public/js/sales_order.js

If the file does not exist, create it and ensure it is loaded via hooks or doctype_js.

Step 2: Add the Button Using refresh

frappe.ui.form.on('Sales Order', {
refresh: function(frm) {
frm.add_custom_button(__('My Custom Action'), function() {
frappe.msgprint('Button Clicked');
});
}
});

What this does

  • Adds a button labeled My Custom Action
  • Displays a message when clicked
  • Button appears on every form refresh

Verified for Frappe Framework v15

Adding the Button Only in Specific Conditions

Example: Show Button Only When Document Is Submitted

frappe.ui.form.on('Sales Order', {
refresh: function(frm) {
if (frm.doc.docstatus === 1) {
frm.add_custom_button(__('Generate Report'), function() {
frappe.msgprint('Report Generated');
});
}
}
});

Why this matters

  • Prevents invalid user actions
  • Maintains workflow discipline
  • Improves UX consistency

Grouping Custom Buttons Under a Menu

Why Use Button Groups?

Button groups keep the UI clean when multiple actions exist.

Example: Add Button Under “Actions”

frm.add_custom_button(
__('Export Data'),
function() {
frappe.msgprint('Export Started');
},
__('Actions')
);

This places the button inside a dropdown labeled Actions.

Calling a Server-Side Method from a Custom Button

Use Case

  • Trigger backend logic such as:
  • Creating linked records
  • Running validations

Integrating third-party services

Client Script Example

frm.add_custom_button(__('Process Order'), function() {
frappe.call({
method: 'your_app.api.process_order',
args: {
docname: frm.doc.name
},
callback: function(r) {
if (!r.exc) {
frappe.msgprint('Order Processed Successfully');
}
}
});
});

Server-Side Python Method (v15-Compatible)

import frappe
@frappe.whitelist()
def process_order(docname):
doc = frappe.get_doc('Sales Order', docname)
# business logic here
return True

Uses @frappe.whitelist() as required in v15
No deprecated APIs used

Best Practices for Custom Buttons in Frappe

UI & UX Best Practices

  • Avoid too many buttons on refresh
  • Use clear, action-oriented labels
  • Group related actions logically

Technical Best Practices

  • Always wrap logic in conditions
  • Avoid heavy logic in client scripts
  • Prefer server-side processing for data changes

Common Mistakes to Avoid

Mistake Why It’s a Problem
Adding buttons outside refresh Button may not render
Heavy logic in JS Performance issues
No permission checks Security risk
Not grouping buttons Cluttered UI

Troubleshooting Custom Button Issues

Button Not Showing?

Check:

  • Correct DocType name
  • JS file loaded properly
  • No JavaScript console errors

Button Click Does Nothing?

Verify:

  • Function binding
  • frappe.call method path
  • Server method is whitelisted

Advanced Use Cases

1. Disable Button After Click

frm.add_custom_button(__('Submit Once'), function(btn) {
btn.prop('disabled', true);
});

2. Redirect to Another DocType

frappe.set_route('Form', 'Customer', frm.doc.customer);

Integration Patterns

Custom buttons are commonly used to integrate:

  • ERPNext workflows
  • External REST APIs
  • Background jobs
  • Custom reports

They act as controlled manual triggers in enterprise systems.

Target Audience Tags

  • ERPNext Developers
  • Frappe Framework Developers
  • Technical Consultants
  • ERP Customization Teams

Industry Relevance

Custom buttons are widely used in:

  • Manufacturing ERP workflows
  • Finance approval systems
  • Sales automation
  • Compliance-driven industries

Summary: Why Custom Buttons Matter

Custom buttons in Frappe Framework v15 provide a clean, controlled way to extend form functionality without breaking standard workflows. When implemented correctly, they improve usability, enforce business logic, and support scalable ERP customizations.
This approach is officially supported, upgrade-safe, and production-ready.

Rating: 0 / 5 (0 votes)