Frappe Client Scriptjavascript

How to Make a Field Read-Only Dynamically in Frappe ERPNext

Make Read only field

Learn to dynamically set field properties like read-only, required, or options in ERPNext and Frappe using Client Scripts with cur_frm.set_df_property.

In Frappe and ERPNext, creating a dynamic and responsive user interface is key to building effective applications. One common requirement is to change a field's properties based on user input or document state, such as making a field read-only after a document is submitted or based on the value of another field. This can be easily achieved using Frappe's Client Script API.

This guide explores the two primary methods for controlling field properties on the client-side: the standard `cur_frm.set_df_property` function and the more direct `frappe.meta.get_docfield` method. We'll cover how to make fields read-only, required, and even how to update options for select fields.

javascript
1// Method 1: Using cur_frm.set_df_property (Recommended)
2
3// Make a field read-only
4cur_frm.set_df_property("net_weight", "read_only", 1);
5
6// Make a field required based on a condition
7cur_frm.set_df_property("cheque_no", "reqd", doc.voucher_type == "Bank Entry");
8
9// General Syntax: cur_frm.set_df_property(FIELDNAME, PROPERTY, VALUE);
10
11
12// Method 2: Directly manipulating the docfield object
13
14var df = frappe.meta.get_docfield("Sales Invoice", "customer_name", cur_frm.doc.name);
15if (df) {
16 df.read_only = 1;
17 cur_frm.refresh_field("customer_name"); // UI refresh is needed
18}
19
20// Example: Dynamically setting options for a Select field in a child table
21var child_df = frappe.meta.get_docfield("Employer Project Details", "company_name", cur_frm.doc.name);
22if(child_df) {
23 child_df.options = ["Tech M", "Wipro", "TCS"];
24 cur_frm.refresh_field("employer_project_details"); // Refresh the whole child table field
25}

Understanding This Code

What It Does

This snippet demonstrates how to programmatically change a field's properties, such as making it read-only, required, or updating its options, directly from a Frappe Client Script.

When To Use

Use this in Client Script triggers like `onload`, `refresh`, or on a field's `onchange` event to create a responsive and context-aware user interface in any DocType form.

Prerequisites

  • Basic understanding of Frappe DocTypes
  • Familiarity with creating Client Scripts in Frappe.

Key Concepts

Important ideas to understand in this code

cur_frm

A global object in Frappe Client Scripts that represents the current form being viewed. It provides access to the document's data (`cur_frm.doc`), metadata, and a rich API for form manipulations.

Learn more

cur_frm.set_df_property

The standard API function to change a property of a DocField. It takes three arguments: the fieldname, the property to change (e.g., 'read_only', 'reqd', 'hidden', 'options'), and the new value. This method automatically handles UI refreshes.

Learn more

frappe.meta.get_docfield

A lower-level function that retrieves the complete DocField object for a given field. This is useful for more complex manipulations but requires a manual UI refresh using `cur_frm.refresh_field()` after modification.

Learn more

Client Script Events

These are JavaScript triggers that execute code at specific points in the form lifecycle. Common events include `onload` (when the form loads), `refresh` (after data is saved/refreshed), and `field_name_onchange` (when a specific field's value changes).

Learn more

Step-by-Step Tutorial

Follow along to understand how this code works

1

Identify the DocType and Fields

First, determine which DocType you want to modify. For this example, we'll use the 'Sales Order' DocType. We want to make the 'delivery_date' field read-only if the 'status' is 'Delivered'.

javascript
// DocType: Sales Order
// Trigger Field: status
// Target Field: delivery_date
Next Step
2

Create a New Client Script

Navigate to 'Client Script' from the Awesome Bar. Click 'Add Client Script', and select 'Sales Order' for the 'DocType'.

text
// In ERPNext Desk:
// Go to > Client Script List > Add Client Script
// Select DocType: Sales Order
Next Step
3

Write the Script Logic

We'll use the `refresh` event handler. This code will run every time the form is loaded or refreshed. It checks the document's status and sets the 'read_only' property accordingly.

javascript
frappe.ui.form.on('Sales Order', {
    refresh: function(frm) {
        // Set a variable for the condition to make it cleaner
        var is_delivered = frm.doc.status === 'Delivered';

        // Set the 'delivery_date' field's read_only property
        frm.set_df_property('delivery_date', 'read_only', is_delivered);
    }
});
Next Step
4

Save and Test

Save the Client Script and ensure it is enabled. Now, navigate to any 'Sales Order' document. If the status is 'Delivered', the 'Delivery Date' field will be non-editable. If you change the status to something else and save, the field will become editable again upon refresh.

text
// 1. Save the Client Script.
// 2. Make sure the 'Enabled' checkbox is checked.
// 3. Go to a Sales Order form and reload the page.
// 4. Observe the 'delivery_date' field's state based on the 'status'.

Common Issues & Solutions

Troubleshoot problems you might encounter