Microsoft Dynamics 365: How to filter lookup field by using JavaScript

Welcome everyone, hope you like this post and find this information somehow helpful.

In this post we are going to talk about filtering a lookup field in CRM by using a JavaScript web resource. The business scenario in this case is about filtering the account lookup field in a contact record based on the team that the user is assigned to. Briefly speaking, this means that when creating a contact record, the user should have the ability to only select as account lookup record only the accounts that are assigned to the team that the user is part of. This can apply in different cases depending on the purpose or the business goal that you are trying to achieve, such as filtering only team-related records to a lookup field. For this task I will guide you on how to filter the account lookup field records based on the user team and accounts assigned to that team.

I am going to break down the creation process of this web resource in the steps below:

  1. Open Visual Studio Code and create a new JavaScript file.
  2. Copy and paste the code below then save file:
function getUserTeam(executionContext) {

    //variable to get form context in order to perform actions on entity form

    formContext = executionContext.getFormContext();

    var guid = "[A-z0-9]{8}-[A-z0-9]{4}-[A-z0-9]{4}-[A-z0-9]{4}-[A-z0-9]{12}";

    var userId = Xrm.Page.context.getUserId();

    userId = userId.match(guid);

    userId = userId.input;

    //retrieve teamIds of the teams current user belongs to

    var userTeamsQuery = "TeamMembershipSet?$select=TeamId&$filter=SystemUserId eq guid'" + userId + "'";

    var userTeams = makeRequest(userTeamsQuery);

    var teamQuery = null;

    var teams = null;

    if (userTeams !== null) {

        for (var i = 0; i < userTeams.length; i++) {

            userTeams[i] = userTeams[i].TeamId;

            var teamId = "{" + userTeams[i] + "}";

            //retrieve name and teamIds of the teams via given teamId that we already have above

            teamQuery = "TeamSet?$select=Name, TeamId&$filter=TeamId eq guid'" + teamId + "'";

            teams = makeRequest(teamQuery);

        }

    }

    //getting control of the lookup field

    formContext.getControl("fisoft_account_lookup").addPreSearch(filterCustomerAccounts);

    //filtering the lookup field on presearch

    function filterCustomerAccounts() {

        var accountFilter = "<filter><condition attribute='ownerid' operator='eq' value='" + teamId + "' /></filter>";

        formContext.getControl("fisoft_account_lookup").addCustomFilter(accountFilter, "fisoft_account");

    }

}

function GetRequestObject() {

    if (window.XMLHttpRequest) {

        return new window.XMLHttpRequest;

    } else {

        try {

            return new ActiveXObject("MSXML2.XMLHTTP.3.0");

        } catch (ex) {

            return null;

        }

    }

}

function makeRequest(query) {

    var serverUrl = Xrm.Page.context.getClientUrl();

    var oDataEndpointUrl = serverUrl + "/XRMServices/2011/OrganizationData.svc/";

    oDataEndpointUrl += query;

    var service = GetRequestObject();

    if (service != null) {

        service.open("GET", oDataEndpointUrl, false);

        service.setRequestHeader("X-Requested-With", "XMLHttpRequest");

        service.setRequestHeader("Accept", "application/json, text/javascript, */*");

        service.send(null);

        var retrieved = JSON.parse(service.responseText).d;

        var results = new Array();

        for (var i = 0; i < retrieved.results.length; i++) {

            results.push(retrieved.results[i]);

        }

        return results;

    }

    return null;

}

This script consists of getUserTeam, getRequestObject and makeRequest functions. What it basically does is that retrieves the teams in which the current user is a part of and then based on condition it will filter the lookup field by using the addPreSearch() function.I will get on an in-depth view for better understanding by breaking down the getUserTeam() function of this script:

The variable “userTeamsQuery” stores a query which is executed by makeRequest() function. It filters teams by comparing the system user ID and the current user ID, so it extracts only the teams in which is a member of.

Then there is a for loop which retrieves team IDs and the name of each team that got filtered:

for (var i = 0; i < userTeams.length; i++) {
            userTeams[i] = userTeams[i].TeamId;
            var teamId = "{" + userTeams[i] + "}";
            //retrieve name and teamIds of the teams via given teamId that we already have above
            teamQuery = "TeamSet?$select=Name, TeamId&$filter=TeamId eq guid'" + teamId + "'";
            teams = makeRequest(teamQuery);
        }
The function that performs the filtering of the lookup field is filterCustomerAccounts():
//filtering the lookup field on presearch
    function filterCustomerAccounts() {
        var accountFilter = "<filter><condition attribute='ownerid' operator='eq' value='" + teamId + "' /></filter>";
        formContext.getControl("fisoft_account_lookup").addCustomFilter(accountFilter, "fisoft_account");
    }

It executes a query which extracts only account records where the owner ID is equal to the team ID, so the account lookup field will only show records that are assigned to a team to which the current user belongs to. The code line below gets control of the lookup field and uses addPreSearch() function and assigns the filterCustomerAccounts() to it so the filtering can be completed:

//getting control of the lookup field
    formContext.getControl("fisoft_account_lookup").addPreSearch(filterCustomerAccounts);
Now let’s get to the CRM part where we upload the web resource and put it to use.
1. First off, make sure you create two entities called Contact and Account. They will both have the name field and owner field created by default, so you just need to add an account lookup field on Contact entity that you created. The lookup field will reflect the name of account records that you will create later on. Also, on the main form of Contact entity include name, account (lookup) and owner, the main form of Account should have only name and owner as fields. UI should look like this:
2. You would like to navigate to Settings > Advanced Settings > Solutions > Choose the solution where the entity you will work on is located. Then navigate to New > Web Resource as illustrated below:
3. Create a new web resource as illustrated below:
This is the JavaScript web resource which I have named as ‘fisoft_account_lookup_filter’ and that is step 1. Step 2 is the display name of the web resource, step 3 you choose the type of it and in this case it is a script. Step 4 is about clicking on text editor button and pasting the JavaScript code inside. After that step 5 and 6 is about saving the web resource first then publishing it.

4. After saving and publishing both of the created web resources, navigate to Entities > Select the entity > Forms > Main Form > Form Properties. The page should look like this:

Then click on Add and search by the logical name of the created JavaScript web resource and then click Add as illustrated below:
Then the page should look like this:
5. Click on the Add button of Event Handlers section in order to add the script to control the form and make sure parameters look like this:
6. Save and publish the form:
7. If you are not aware of teams on Dynamics 365 yet:
Create teams with different names, in this case I have created Team 1, Team 2 and Team 3. I am part of Team 1 only so we will test how the script will filter the account lookup for me so I will have only the accounts of my team selectable. Also, I created three account records so one for each team:

8. Now I will show you a demo of creating a contact record and the account lookup field being filtered:

Wrapping it up, this post was about using JavaScript in Dynamics 365 CRM to filter a lookup field which in this case was an account lookup field filtered based on the team to which both the user and the account record was assigned to.