Use this file to discover all available pages before exploring further.
Forms are the primary interface for creating and editing documents in Frappe. They are automatically generated from DocType metadata and can be customized through scripts, custom fields, and form layouts.
Frappe forms are rendered dynamically based on DocType metadata:
Server-side: DocType fields, permissions, and validation rules
Client-side: JavaScript for UI interactions, field events, and custom behavior
Layout: Section breaks, column breaks, and tabs organize fields visually
// Form script example (client-side)frappe.ui.form.on('Sales Order', { refresh: function(frm) { // Called when form is loaded or refreshed console.log('Form loaded:', frm.doc.name); }, customer: function(frm) { // Called when customer field changes frm.set_value('customer_name', 'Updated Value'); }});
frappe.ui.form.on('DocType Name', { // Document level events refresh: function(frm) { // Form is loaded or refreshed }, before_load: function(frm) { // Before document is loaded }, onload: function(frm) { // After document is loaded }, before_save: function(frm) { // Before document is saved (can prevent save) if (!frm.doc.customer) { frappe.throw('Customer is required'); return false; } }, after_save: function(frm) { // After document is saved frappe.show_alert('Document saved successfully'); }, validate: function(frm) { // Validation before save }, before_submit: function(frm) { // Before document is submitted }, on_submit: function(frm) { // After document is submitted }});
// Show/hide fieldsfrm.set_df_property('customer_name', 'hidden', 1);frm.set_df_property('customer_name', 'hidden', 0);// Make field read-onlyfrm.set_df_property('customer', 'read_only', 1);// Make field mandatoryfrm.set_df_property('delivery_date', 'reqd', 1);// Set field labelfrm.set_df_property('customer', 'label', 'Client');// Set field descriptionfrm.set_df_property('customer', 'description', 'Select the client from the list');// Refresh single fieldfrm.refresh_field('customer');// Refresh multiple fieldsfrm.refresh_fields(['customer', 'customer_name', 'items']);
# Show field only when condition is true{ 'fieldname': 'tax_id', 'label': 'Tax ID', 'fieldtype': 'Data', 'depends_on': 'eval:doc.is_company==1' # Show only for companies}# Multiple conditions{ 'depends_on': 'eval:doc.customer && doc.status=="Draft"'}
# Make field mandatory based on condition{ 'fieldname': 'gstin', 'label': 'GSTIN', 'fieldtype': 'Data', 'mandatory_depends_on': 'eval:doc.country=="India"'}
# Make field read-only based on condition{ 'fieldname': 'customer', 'label': 'Customer', 'fieldtype': 'Link', 'options': 'Customer', 'read_only_depends_on': 'eval:doc.docstatus==1'}