Lookup Dialog in CRM 2013 with custom FetchXML filtering

Dynamics 2013 introduced some new cool functions to filter lookup during “run-time”, so we can do something like this:

var ctrl = Xrm.Page.getControl('some_lookup_control');
ctrl.addPreSearch(function() {
 var someFetchXml = '<filter type="and"><condition attribute="some_field" operator="eq" value="some_value" /></filter>';

It all works nice and easy when You have Lookup on field. But sometimes You don’t want (or can’t) to have lookup on Your form. Let’s say You want to give user ability to select some entity and put that data into Your fields. To make it look nice, let’s use CRM Lookup dialogs. To simply display Lookup dialog we use Xrm.Internal namespace (which of course is not supported):

var url = "/_controls/lookup/lookupsingle.aspx?objecttypes=" + Xrm.Internal.getEntityCode('your_entity_to_search');
// uncomment this and change view GUID to preselect default View selected on form
// var viewId = '6e501e6c-7a59-4423-914b-0602d30c6fe9';
// url = url + "&DefaultViewId=%7b" + viewId + "%7d";
var DialogOptions = new Xrm.DialogOptions();
DialogOptions.width = 600;
DialogOptions.height = 600;
Xrm.Internal.openDialog(Mscrm.CrmUri.create(url).toString(), DialogOptions, null, null, function(returnValue) {
 if (!IsNull(returnValue) && !IsNull(returnValue.items) && !IsNull(returnValue.items[0].id)) {
  var id = returnValue.items[0].id;
  // use the id of selected record to populate some other field etc.

Hook this to some button onclick event and it should be working fine, giving user CRM experience.

This should be working fine, but let’s say You want to filter this based on some field on Your form. You can’t use addPreSearch becuase You don’t have lookup. Digging into CRM JavaScript source code, let’s see how CRM do this.

First let’s look at addCustomFilter:

addCustomFilter: function(fetchXmlFilter, entityType) {
  if (IsNull(entityType)) entityType = Mscrm.InternalUtilities._String.Empty;
  Array.add(this.$o_4, entityType);
  Array.add(this.$n_4, CrmEncodeDecode.CrmUrlEncode(fetchXmlFilter))

Nothing fancy, now the part where data is actually loading:

$v_B += "&customFilter=" + CrmEncodeDecode.CrmUrlEncode(this.$n_4.join("="));
$v_B += "&customFilterTypes=" + CrmEncodeDecode.CrmUrlEncode(this.$o_4.join(","));

As we see, all we need to do is add those 2 keys to our query string:

var someFetchXml = '<filter type="and"><condition attribute="some_field" operator="eq" value="some_value" /></filter>';
var filter = "&customFilter=" + CrmEncodeDecode.CrmUrlEncode(CrmEncodeDecode.CrmUrlEncode(someFetchXml)) + "&customFilterTypes=";
url = url + filter;

And yes, we need to double encode our FetchXML, as it is later put onto another parameter:

$v_0.SetParameter("additionalParameters", $v_B);

This way, we can have CRM lookup dialog with custom filtering, also user can enter extra search text. Hope this helps someone 🙂