Every screen in the Desk is rendered inside a frappe.ui.Page object. When you create a Page doctype, Frappe loads its JavaScript file and calls on_page_load with the page wrapper. Inside that handler you build a frappe.ui.Page and add your own content, buttons, and form fields.
frappe.pages["my-page"].on_page_load = function (wrapper) {
let page = frappe.ui.make_app_page({
parent: wrapper,
title: "My Page",
single_column: true,
});
page.set_primary_action(__("New"), () => create_new());
};
frappe.ui.make_app_page
Creates a Page and attaches it to a parent element.
let page = frappe.ui.make_app_page({
parent: wrapper, // DOM element or jQuery object
title: "My Page",
single_column: true, // create a page without the sidebar column
});
The instance returned is your handle for everything below.
Title and subtitle
Use set_title to set the page heading. This also updates the browser tab title.
page.set_title("My Page");
Use set_title_sub to show secondary text next to the heading.
page.set_title_sub("Subtitle");
Indicator
set_indicator shows a colored status dot with a label.
page.set_indicator(__("Pending"), "orange");
clear_indicator removes it.
page.clear_indicator();
Primary and secondary actions
set_primary_action(label, click, icon, working_label) adds the main button at
the top right. The icon shows in mobile view, and working_label is the text
shown while the click handler runs. It returns the button element.
let btn = page.set_primary_action(__("New"), () => create_new(), "add");
set_secondary_action takes the same arguments and adds a second button beside it.
page.set_secondary_action(__("Refresh"), () => refresh(), "refresh");
Clear either one with clear_primary_action() or clear_secondary_action().
Menu and action items
add_menu_item(label, click, standard) adds an item to the Menu dropdown. Pass
true for standard to keep the item across page reloads in developer mode.
page.add_menu_item(__("Send Email"), () => open_email_dialog());
add_action_item(label, click, standard) adds an item to the Actions dropdown.
page.add_action_item(__("Delete"), () => delete_items());
Remove the dropdowns with clear_menu() and clear_actions_menu().
Inner buttons
add_inner_button(label, action, group, type, align_right) adds a button to the
inner toolbar. Pass a group to place it inside a dropdown group, and type to
set the button style.
// standalone button
page.add_inner_button(__("Update Posts"), () => update_posts());
// button inside a "Make" group
page.add_inner_button(__("New Post"), () => new_post(), "Make");
change_inner_button_type(label, group, type) restyles an existing button. Pass
null for the group of an ungrouped button.
page.change_inner_button_type("Update Posts", null, "primary");
page.change_inner_button_type("Delete Posts", "Actions", "danger");
remove_inner_button(label, group) removes a single button, and
clear_inner_toolbar() removes the whole toolbar.
page.remove_inner_button("Update Posts");
page.remove_inner_button("New Post", "Make");
Page form fields
add_field(df) adds a form control to the page form area. It takes a fieldtype
definition, the same shape used elsewhere in Frappe, and returns the control.
let field = page.add_field({
label: "Status",
fieldtype: "Select",
fieldname: "status",
options: ["Open", "Closed", "Cancelled"],
change() {
console.log(field.get_value());
},
});
get_form_values() returns all field values as an object keyed by fieldname.
let values = page.get_form_values();
// { status: "Open", priority: "Low" }
clear_fields() removes all fields from the form area.
page.clear_fields();