web
You’re offline. This is a read only version of the page.
close
Skip to main content

Announcements

No record found.

News and Announcements icon
Community site session details

Community site session details

Session Id :
Microsoft Dynamics 365 | Integration, Dataverse...
Suggested Answer

Filter Lookup with a N:N relationship

(1) ShareShare
ReportReport
Posted on by 447
Hi all, we are trying to filter a lookup that has a N:N relationship to another entity but seems like the filtering is not working. We have the below: 
 
  • Entity named Industry (example; Industry A, Industry B)
  • Entity named Applications (example; Application A, Application B, Application C, Application D)
    • This entity has a N:N (many to many) reationship with Industry. 
  • Extended the standard quote entity with;
    • a new lookup to the industry entity, exposed in the Quote Main form
    • a new lookup to the applications entity, exposed in the Quote Main form
 
This means that in the quote form, the user selects the Industry first and then, the Application lookup should be automatically filtered to show only applications related to the selected entity. 
 
We created a Web Resource in which we have 2 functions as per below. On the event OnChange of the Industry lookup field in the quote main form, we are calling the setPreSearch function. 
Unfortunately the application lookup is not being filtered. Any guesses to what's wrong here? We've debugged the function filterCustomerApplicationsbyIndustry and can see that the filterXML is being done correctly but somehow seems like it is being lost between the functions calling each other. 
 
We have also tried calling the filterCustomerApplicationsbyIndustry function in the setPreSearch function like this, but has not worked either.
attribute.controls.forEach(control => control.addPreSearch(PublisherA.IndustryApplication.filterCustomerApplicationsbyIndustry(executionContext))) 
 
 
Below is the javascript we did: 
 
(function () {
    PublisherA.IndustryApplication.setPreSearch = function (executionContext) {
        debugger;
        var formContext = executionContext.getFormContext()
        var attribute = formContext.getAttribute("pubA_customerapplication")
        attribute.controls.forEach(control => control.addPreSearch(PublisherA.IndustryApplication.filterCustomerApplicationsbyIndustry(executionContext))) 
    }

    PublisherA.IndustryApplication.filterCustomerApplicationsbyIndustry = function (executionContext) {
        var formContext = executionContext.getFormContext();
        var entityName = formContext.data.entity.getEntityName();

        // Replace these with actual logical names on each entity form
        var industryFieldLogicalName;
        var customerAppFieldLogicalName;

        switch (entityName) {
            case "quote":
                industryFieldLogicalName = "pubA_industry"; //field schema name on Quote
                customerAppFieldLogicalName = "pubA_customerapplication"; //field schema name on Quote
                break;

            case "order":
                industryFieldLogicalName = "pubA_industry"; // field schema name on Order
                customerAppFieldLogicalName = "pubA_customerapplication"; // field schema name on Order
                break;

            default:
                console.log("Entity not supported for filtering: " + entityName);
                return;
        }

        var industryAttribute = formContext.getAttribute(industryFieldLogicalName);
        var customerAppControl = formContext.getControl(customerAppFieldLogicalName);

        if (!industryAttribute || !customerAppControl) {
            console.error("Field logical names are incorrect or controls not found.");
            return;
        }

        var industryValue = industryAttribute.getValue();
        if (!industryValue || industryValue.length === 0) {
            // Clear filters if no industry selected
            customerAppControl.clearCustomFilter();
            return;
        }

        var industryId = industryValue[0].id.replace("{", "").replace("}", "");
        debugger;
        // Replace below tokens with your actual metadata logical names:
        var customerAppEntityLogicalName = "pubA_customerapplicationindustry";          // table logical name
        var customerAppPkLogicalName = "pubA_customerapplicationindustryid";        // PK of Customer Application
        var industryPkLogicalName = "pubA_industryid";                   // PK of Industry        
        var nnNavigationPropertyOnApp = "pubA_CustomerApplicationIndustry_pubA_Industry_pubA_Industry"; //relationship schema name

        var query =
            "?$select=" + customerAppPkLogicalName +
            "&$expand=" + nnNavigationPropertyOnApp + "($select=" + industryPkLogicalName + ")" +
            "&$filter=" + nnNavigationPropertyOnApp + "/any(i:i/" + industryPkLogicalName + " eq " + industryId + ")";

        Xrm.WebApi.retrieveMultipleRecords(customerAppEntityLogicalName, query).then(
            function (result) {
                if (result.entities.length > 0) {
                    var filterXml = "<filter type='and'><condition attribute='" + customerAppPkLogicalName + "' operator='in'>";
                    result.entities.forEach(function (app) {
                        filterXml += "<value>" + app[customerAppPkLogicalName] + "</value>";
                    });
                    filterXml += "</condition></filter>";

                    customerAppControl.addCustomFilter(filterXml, customerAppEntityLogicalName);
                } else {
                    // No matches; clear filter
                    customerAppControl.clearCustomFilter();
                }
            },
            function (error) {
                console.error(error.message);
            }
        );
    }
})();
 
Thanks in advance for your help! 
 
 
 
Categories:
I have the same question (0)
  • Suggested answer
    ManoVerse Profile Picture
    884 Super User 2026 Season 1 on at
    addPreSearch expects a function reference, not the result of a function call , control.addPreSearch(PublisherA.IndustryApplication.filterCustomerApplicationsbyIndustry(executionContext))  this calls function immediately and passes its return value which would come as undefined) instead of passing the function.
     
    Correct approach should be like this 
    control.addPreSearch(function () {
        PublisherA.IndustryApplication.filterCustomerApplicationsbyIndustry(executionContext);
    });  This ensures the function runs when the lookup search happens, not during form load.
     
    customerAppControl.addCustomFilter(filterXml, customerAppEntityLogicalName);   
    make sure filter must apply to the lookup target entity (Applications), not the intersect entity
     
    Also, seems you are filtering on pubA_customerapplicationindustryid (PK of the intersect table), but the lookup expects the PK of the Application entity.
    Instead, build the filter using the Application entity’s primary key (e.g pubA_customerapplicationid).
     
     
    Solution : timing is very important while working on presearch , addPreSearch only works if the filter is applied before the user opens the lookup dropdown ,
    If the async Xrm.WebApi.retrieveMultipleRecords call hasn’t finished before the dropdown opens, the filter won’t apply so preload or use synchronous logic
     
     
     
    PublisherA.IndustryApplication.setPreSearch = function (executionContext) {
        var formcontext = executionContext.getFormContext();
        var attribute = formContext.getAttribute("puba_customerapplication");
        attribute.controls.forEach(function (control) {
            control.addPreSearch(function () {
                PublisherA.IndustryApplication.filterCustomerApplicationsbyIndustry(executionContext);
            });
        });
    };
     
    checklist:
    1. Pass a function reference to addPreSearch.
    2. Use the lookup target entity name in addCustomFilter.
    3. Filter on the correct attribute (Application PK).
    4. Ensure async timing doesn’t break the filter.

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Introducing the 2026 Season 1 community Super Users

Congratulations to our 2026 Super Stars!

Congratulations to our 2025 Community Spotlights

Thanks to all of our 2025 Community Spotlight stars!

Leaderboard > Microsoft Dynamics 365 | Integration, Dataverse, and general topics

#1
11manish Profile Picture

11manish 156

#2
Pallavi Phade Profile Picture

Pallavi Phade 102 Super User 2026 Season 1

#3
Abhilash Warrier Profile Picture

Abhilash Warrier 55 Super User 2026 Season 1

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans