How to Create a Mapped Document from a Custom Button in Frappe
Map Document using custom buttonLearn how to add a custom button to a Frappe form that triggers the creation of a new, mapped document using the 'frappe.model.open_mapped_doc' method in a Client Script.
This guide demonstrates how to create a custom button on a Frappe form that, when clicked, initiates the creation of a new document by mapping data from the current form. This is a common requirement for streamlining workflows, such as creating a 'Meeting' from a 'Meeting Schedule'.
The solution involves using a Client Script to hook into the form's `refresh` event, adding the button, and then calling the `frappe.model.open_mapped_doc` utility function. This function calls a whitelisted Python server method to handle the data mapping and document creation logic.
1 frappe.ui.form.on('Meeting Schedule', { 2 refresh: function(frm) { 3 frm.add_custom_button(__("Create Meeting"), function() { 4 frappe.model.open_mapped_doc({ 5 method : "eie.eie.doctype.meeting_schedule.meeting_schedule.make_meeting", 6 frm : cur_frm 7 }) 8 }) 9 } 10 });
Understanding This Code
What It Does
Adds a custom button named 'Create Meeting' to the 'Meeting Schedule' form. Clicking this button triggers a server-side Python method to create a new, mapped 'Meeting' document.
When To Use
Use this approach when you need to provide users with a one-click action to create a related document from an existing one, pre-filling data based on defined mapping rules.
Key Concepts
Important ideas to understand in this code
Form Event Triggers
The 'frappe.ui.form.on' method is a client-side API used to attach event handlers to DocType forms. The 'refresh' event is triggered every time the form is loaded or reloaded, making it the ideal place to add custom buttons or modify form behavior.
Learn moreAdding Custom Buttons
This Form object method, 'frm.add_custom_button', allows developers to dynamically add buttons to the form's header. It takes the button label and a callback function to be executed when the button is clicked.
Learn moreCreating Mapped Documents
A powerful utility that streamlines the creation of a new document from an existing one. It calls a specified server-side (Python) method, passing the current form's context. The server method is responsible for creating the new document and returning its details, after which the client is redirected to the new document's form.
Learn moreStep-by-Step Tutorial
Follow along to understand how this code works
Create a New Client Script
First, navigate to the 'Client Script' list in your Frappe desk. Create a new script and select 'Meeting Schedule' as the DocType to which it applies.
// No code for this step. This is a UI action.Hook into the Refresh Event
Use the 'frappe.ui.form.on' method to specify that your code should run every time the 'Meeting Schedule' form is refreshed.
frappe.ui.form.on('Meeting Schedule', {
refresh: function(frm) {
// Your button logic will go here
}
});Add the Custom Button
Inside the 'refresh' function, call 'frm.add_custom_button'. The first argument is the button's label, and the second is the function that will execute when the button is clicked.
frm.add_custom_button(__("Create Meeting"), function() {
// The action to perform on click goes here
});Call 'open_mapped_doc'
In the button's click handler, call 'frappe.model.open_mapped_doc'. This function requires an object specifying the whitelisted Python 'method' to call and the current form 'frm' to pass as context.
frappe.model.open_mapped_doc({
method : "eie.eie.doctype.meeting_schedule.meeting_schedule.make_meeting",
frm : cur_frm
})Implement the Server-Side Python Method
The 'method' specified points to a Python function. You must create this function in the specified path (e.g., 'meeting_schedule.py') and whitelist it with '@frappe.whitelist()' for it to be callable from the client-side.
import frappe
from frappe.model.mapper import get_mapped_doc
@frappe.whitelist()
def make_meeting(source_name, method='post'):
doc = get_mapped_doc('Meeting Schedule', source_name, {
'Meeting Schedule': {
'doctype': 'Meeting',
'field_map': {
'name': 'meeting_schedule',
# map other fields here, e.g., 'subject': 'subject'
}
}
})
doc.insert()
return docCommon Issues & Solutions
Troubleshoot problems you might encounter