Action Buttons in Column
Use Case
As seen above, we want an inline “Close” button for each row in the above report. Clicking on this button should close the corresponding ToDo and refresh the report automatically.
The Report Python Script
The logic below is pretty simple. We are fetching the status
, description
and name
for the ToDo documents that are either created by or allocated to the currently logged in user using or_filters
:
import frappe
def execute(filters=None): return get_columns(), get_data()
def get_data(): current_user = frappe.session.user todos = frappe.get_all( "ToDo", filters={"status": "Open"}, # created by or allocated to current user or_filters=[{"owner": current_user}, {"allocated_to": current_user}], fields=["name", "description", "status"], ) return todos
# 3 columnsdef get_columns(): return [ { "label": "Description", "fieldname": "description", "fieldtype": "Data", "width": 400, }, {"label": "Status", "fieldname": "status", "fieldtype": "Data", "width": 200},
# This column will be used to render the close buttons { "label": "Close Action", "fieldname": "name", "fieldtype": "Data", "width": 150, }, ]
The JS Script
We will basically be making (a clever 😆) use of the formatter
feature of query report scripts to render a button in every row of the “Close Action” column (field name is name):
frappe.query_reports["My ToDos"] = { filters: [], onload(report) { // add an action button to visit ToDo List View report.page.add_inner_button("Go to ToDo List", () => { frappe.set_route("List", "ToDo"); }); }, formatter(value, row, column, data, default_formatter) { // Show a button instead of the "name" if (column.fieldname == "name") { const button_html = `<button class="btn btn-default btn-xs" onclick="frappe.query_reports['My ToDos'].close_todo('${value}')">Close</button>`; value = button_html; } return default_formatter(value, row, column, data); }, close_todo(name) { frappe.db.set_value("ToDo", name, "status", "Closed").then(() => { // refresh this report and show alert frappe.query_report.refresh(); frappe.show_alert("ToDo Closed Successfully!"); }); },};
Some Notes From Above Script
-
We are using the
add_inner_button
JavaScript API to add a button at the top of the report page:report.page.add_inner_button("Go to ToDo List", () => {frappe.set_route("List", "ToDo");}); -
frappe.query_report
refers to the currently open report view. (analogous tocur_frm
in form view andcur_list
in list view) -
On click of a button, we are triggering the
close_todo
method of the report script:// ${value} is the name of the ToDo document we sent from backendfrappe.query_reports['My ToDos'].close_todo('${value}')