Frappe Client ScriptJavascript

How to Set Dynamic Query Filters for Contact Link Fields in Frappe

Contact Query Filter

Learn to apply dynamic filters to Contact link fields in Frappe/ERPNext using the cur_frm.set_query client script method for both parent and child table fields.

In Frappe ERPNext, providing users with relevant choices in Link Fields is crucial for data accuracy and user experience. The `cur_frm.set_query` method is the standard way to dynamically filter the list of records that appear in a Link Field dropdown.

This snippet provides two powerful examples. The first demonstrates how to filter a standard Link Field on the main form. The second, more advanced example, shows how to apply a filter to a Link Field inside a Child Table, ensuring context-aware selections in complex forms.

javascript
1// Contact Query for a field on the parent document
2cur_frm.set_query("broker_contact", function() {
3 if(cur_frm.doc.broker) {
4 return {
5 query: "frappe.contacts.doctype.contact.contact.contact_query",
6 filters: { link_doctype: "Supplier", link_name: cur_frm.doc.broker }
7 };
8 }
9 else frappe.throw(__("Please set Broker"));
10});
11
12// Contact query for a field within a Child Table
13cur_frm.set_query("contact", "escalations", function(doc, cdt, cdn) {
14 return {
15 query: "frappe.contacts.doctype.contact.contact.contact_query",
16 filters: { link_doctype: "Customer", link_name: cur_frm.doc.customer }
17 };
18});

Understanding This Code

What It Does

This script dynamically filters the list of selectable contacts in two different Link Fields. The first filter applies to a parent field named 'broker_contact', and the second applies to a 'contact' field within a child table named 'escalations'.

When To Use

Use this script in the 'onload' or 'refresh' event of a DocType's client script to apply filters when the form loads. It can also be used in a field's 'onchange' event to re-apply filters when a dependent value changes (e.g., when the 'broker' or 'customer' field is set).

Prerequisites

  • A DocType with a 'Link' field pointing to the 'Contact' DocType.
  • Basic understanding of Frappe Client Scripting and the DocType form structure.

Key Concepts

Important ideas to understand in this code

cur_frm.set_query

A fundamental Form API method in Frappe used to apply filters to Link and Dynamic Link fields. It takes the fieldname, an optional child table name, and a function that must return a query object with filters.

Learn more

Contact Query Path

`frappe.contacts.doctype.contact.contact.contact_query` is a built-in whitelisted Python method specifically for fetching contacts. It standardizes filtering by a linked document, requiring `link_doctype` and `link_name` in the filters object.

Learn more

Child Table Scripting

When using `set_query` on a child table field, you must provide the child table's fieldname as the second argument. The callback function then receives three arguments: `doc` (the current row's data object), `cdt` (Child DocType), and `cdn` (Child DocName/row ID).

Learn more

Step-by-Step Tutorial

Follow along to understand how this code works

1

Create a New Client Script

Navigate to the DocType list, select the DocType you want to modify, and scroll down to the 'Client Scripts' section. Click 'Add New' to create a new Client Script.

bash
// Example: Navigate to 'Sales Order' DocType > Client Scripts > Add New
Next Step
2

Filter the Parent Link Field

Add the first part of the script. This code targets the 'broker_contact' field. It checks if the 'broker' field (a Link to a Supplier) is set. If so, it filters the contacts to show only those linked to that specific supplier.

javascript
cur_frm.set_query("broker_contact", function() {
	if(cur_frm.doc.broker) {
		return {
			query: "frappe.contacts.doctype.contact.contact.contact_query",
			filters: { link_doctype: "Supplier", link_name: cur_frm.doc.broker } 
		};
	}
	else frappe.throw(__("Please set Broker"));
});
Next Step
3

Filter the Child Table Link Field

Add the second part of the script. This targets a 'contact' field inside a child table named 'escalations'. It filters the contacts to show only those linked to the main document's selected 'customer'. Note the use of `cur_frm.doc.customer` to access the parent document's data.

javascript
cur_frm.set_query("contact", "escalations", function(doc, cdt, cdn) {
	return {
		query: "frappe.contacts.doctype.contact.contact.contact_query",
		filters: { link_doctype: "Customer", link_name: cur_frm.doc.customer } 
	};
});
Next Step
4

Save and Test

Save the Client Script and clear your browser cache (Ctrl+Shift+R). Open a new form for your DocType. The 'broker_contact' and child table 'contact' fields should now be filtered based on the values in the 'broker' and 'customer' fields respectively.

bash
// No code needed for this step. Just test the form functionality.

Common Issues & Solutions

Troubleshoot problems you might encounter