Dynamics CRM Client Scripting: addCustomFilter and addPreSearch

The most common requirement that usually we need to apply is filtering the lookup dynamically based on the state of the current attribute. For example, you have a Custom Approval entity (table) that got a lookup to Customer and Custom Document. Then when the user on the Custom Approval screen, you want to filter the Custom Document based on the Level field (column) that the user can input on the screen + selected Customer field (column). For this scenario, we can apply filters using addPreSearch and addCustomFilter .

Sample scenario

To simplify the meaning of these 2 functions, I would say that addPreSearch is a function to register another function for filtering purpose. While the addCustomFilter is the method that will be invoked for filtering the records and need to be registered on addPreSearch. We only need to register these functions 1 time on the form_onLoad event and here is the sample of the code to make use of these both functions:

var Blog = Blog || {};
Blog.Business = Blog.Business || {};
Blog.Event = Blog.Event || {};

var run;
(function() {
    var LEVEL_LOW = 100000000;
    var LEVEL_MEDIUM = 100000001;
    var LEVEL_HIGH = 100000002;

    this.registerPreSearch = function(context) {
        var filterCustomDocument = function(context) {
            var formContext = context.getFormContext();

            var customerRef = formContext.getAttribute('new_customerid').getValue();
            var level = formContext.getAttribute('new_level').getValue();

            var valid = customerRef && level;
            if (!valid) return;

            var filterXml = [
                '<filter type="and">',
                '<condition attribute="new_customerid" operator="eq" value="' +
                customerRef[0].id +
                '" />',
            ];

            if (level === LEVEL_LOW) {
                filterXml.push(
                    '<condition attribute="new_totalamount" operator="lt" value="200" />'
                );
            } else if (level === LEVEL_MEDIUM) {
                filterXml = filterXml.concat([
                    '<condition attribute="new_totalamount" operator="ge" value="200" />',
                    '<condition attribute="new_totalamount" operator="le" value="500" />',
                ]);
            } else if (level === LEVEL_HIGH) {
                filterXml.push(
                    '<condition attribute="new_totalamount" operator="gt" value="500" />'
                );
            }

            filterXml.push('</filter>');
            formContext
                .getControl('new_customdocumentid')
                .addCustomFilter(filterXml.join(''));
        };

        return (function() {
            if (run) return;

            var formContext = context.getFormContext();
            formContext.getControl('new_customdocumentid').addPreSearch(() => {
                filterCustomDocument(context);
            });
            run = true;
        })();
    };
}.apply(Blog.Business));

(function() {
    this.form_OnLoad = function(context) {
        Blog.Business.registerPreSearch(context);
    };
}.apply(Blog.Event));

From the top code, you will see that there is some business logic to filtering the Custom Documents based on the option set value (Level) and the selected Customer and we just need to use 2 functions to register it. I have never seen any business logic that so complex that we need to register more than 1 addCustomFilter and addPreSearch. Hence using removePreSearch is also not necessary in my opinion. If you want to skip the filtering function, you can do it using a return statement in line 19 on the code above to reserve original function (no filtering).

If you want to filter the record based on the state of the current field in the screen. You also can use the out of the box feature. But unfortunately, this feature not yet can be seen in the newest Form Editor. So you need to check on the classic editor to set this up. Below is a sample of how to filtering the Custom Documents based on the selected Customer.

Set Related Records Filtering

The other thing with the addCustomFilter, you also can combine the existing filter on the selected view with this and the operator for this combination is ‘AND’. So you can optimize the code just for the attribute that will be changed dynamically, and use the rest with the OOB feature.

This is the sample of the data that come out after we apply those code:

Sample result of the filtering

Summary

Sometimes a lot of developers are trapped on the addCustomFilter function. The code for filtering becomes so complex. But actually, they can make use of pre-defined view (and set it as default + can’t change the view) and Related Records Filtering function to simplify the code.

What do you think?

2 thoughts on “Dynamics CRM Client Scripting: addCustomFilter and addPreSearch

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.