When working in Dynamics 365 or Power Apps model-driven apps, it’s common to have forms where you want to restrict a lookup field so it only shows relevant records. A typical scenario is filtering the “User” lookup field to only display users who belong to a specific Team.

In this post, we’ll walk through how to achieve this using JavaScript and FetchXML.

The Scenario

Suppose we have two lookup fields on a form:

  • Team (teamLookupField) → Selects a team.
  • User (userLookupField) → Should display only members of the selected team.

We’ll attach custom JavaScript to filter the User lookup based on the Team selected.

The Code

Below is the JavaScript that makes this happen:

if (typeof(HIMBAP) === "undefined") {

    var HIMBAP = {

        __namespace: true

    };

}

HIMBAP.UserFilterByTeam = {

    AddFilter: function (executionContext, teamLookupField, userLookupField) {

        var formContext = executionContext.getFormContext();

        var userControl = formContext.getControl(userLookupField);

        if (userControl) {

            userControl.addPreSearch(function () {

                HIMBAP.UserFilterByTeam.ApplyTeamFilter(formContext, teamLookupField, userLookupField);

            });

        }

    },

    ApplyTeamFilter: function (formContext, teamLookupField, userLookupField) {

        var teamValue = formContext.getAttribute(teamLookupField).getValue();

        if (teamValue && teamValue.length > 0) {

            var teamId = teamValue[0].id.replace(/\[{}\]/g, "");

            var teamName = teamValue[0].name;

            var viewId = "{D2A5B3E2-8F2C-4D7F-B5AA-1E2F50B66A6D}";

            var entityName = "systemuser";

            var viewDisplayName = "Users in Team: " + teamName;

            var fetchXML = [

                "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='true'>",

                "  <entity name='systemuser'>",

                "    <attribute name='fullname' />",

                "    <attribute name='systemuserid' />",

                "    <order attribute='fullname' descending='false' />",

                "    <link-entity name='teammembership' from='systemuserid' to='systemuserid' intersect='true' visible='false'>",

                "      <link-entity name='team' from='teamid' to='teamid' alias='t'>",

                "        <filter type='and'>",

                "          <condition attribute='teamid' operator='eq' value='" + teamId + "' />",

                "        </filter>",

                "      </link-entity>",

                "    </link-entity>",

                "  </entity>",

                "</fetch>"

            ].join("");

            var layoutXML = [

                "<grid name='resultset' object='8' jump='fullname' select='1' icon='1' preview='1'>",

                "  <row name='result' id='systemuserid'>",

                "    <cell name='fullname' width='300' />",

                "  </row>",

                "</grid>"

            ].join("");

            var control = formContext.getControl(userLookupField);

            if (control) {

                control.addCustomView(viewId, entityName, viewDisplayName, fetchXML, layoutXML, true);

            }

        }

    }

};

How It Works

addUserLookupFilter

  • Runs when the form loads
  • Hooks into the User lookup’s addPreSearch event
  • Calls applyTeamFilter before the lookup query executes

applyTeamFilter

  • Reads the selected Team lookup value
  • Builds a FetchXML query to return only users in that team
  • Uses addCustomView() to replace the default lookup list with filtered results

FetchXML Breakdown

  • systemuser is the main entity
  • teammembership is the intersect entity linking users to teams
  • team is joined to filter by teamid
  • Only users in the selected team are returned

Adding the Script to Your Form

  1. Add the JavaScript file as a Web Resource
  2. Form OnLoad → call: javascriptCopyEdit

addUserLookupFilter(executionContext, "team_field_schema", "user_field_schema");

  1. OnChange event for Team lookup → also call the same function:

    addUserLookupFilter(executionContext, "team_field_schema", "user_field_schema");

Replace:

  • "team_field_schema" → schema name of your Team lookup field
  • "user_field_schema" → schema name of your User lookup field
  1. Publish and test:
  • Select a team → open User lookup → only users from that team are displayed

Conclusion

Filtering users in a lookup field based on a selected team in Dynamics 365 significantly improves form usability and data accuracy. By directly using the addPreSearch and addCustomView methods without any wrapper functions, the logic becomes more straightforward and easier to maintain. This method ensures that users only see relevant records, reducing search time and preventing incorrect selections. It’s a clean, effective way to enhance the user experience in model-driven apps.