How to Set Dynamic Query Filters for Contact Link Fields in Frappe
Contact Query FilterLearn 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.
1 // Contact Query for a field on the parent document 2 cur_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 13 cur_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 moreContact 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 moreChild 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 moreStep-by-Step Tutorial
Follow along to understand how this code works
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.
// Example: Navigate to 'Sales Order' DocType > Client Scripts > Add NewFilter 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.
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"));
});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.
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 }
};
});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.
// No code needed for this step. Just test the form functionality.Common Issues & Solutions
Troubleshoot problems you might encounter