Filtering large List Lookup dropdowns

  • 22 December 2016
  • 17 replies
  • 436 views

Badge +7

Often you will see forms that contain List Lookup controls that draw their data from some list in Sharepoint that contains hundreds or even thousands of elements. This gives the user a less-than-friendly experience trying to find their relevant selection among all those items.

 

Just look at that scroll bar in the following picture - this tells us that there are LOTS of item to select from...

 

 

I set out to create some functionality for filtering those items, so that only items that contained some string entered by the user, would appear. This is the effect I got after implementing the solution described in this post:

 

These are the steps necessary to accomplish this:

 

1) Save the attached JavaScript file in a place from where you can reference it. I usually store my scripts under Site Assets/Scripting. For this example I have stored it as Site Assets/Scripting/NF-Utilities/NF-OptionsFilter.js.

 

I actually use Sharepoint as my source control system, where I only let my users see the published versions. That way I can do development without affecting the users until I am ready. But that's another story wink.png

 

2) Create a Single Line Text Box somewhere in your form - prefereably near the List Lookup control to make it intuitive for the user, that these fields are somehow connected. This is the field that I labelled "Filter replies" in the screenshot above.

3) Go to the Control Settings of the Text Box, and put in a variable name for the field:

4) Now go to the Control Settings of the List Lookup control and assign another variable for this:

5) Open the Settings of the form:

6) Put in a reference to the script under Advanced -> Custom JavaScript Includes:

7) Enter the following code snippet under Custom JavaScript:

    NWF$(document).ready(function(){
        if (Is New Mode || Is Edit Mode) {
            new Filter(varReply, varReplyFilter);
        }
  });
Note: You get the "Is New Mode" and "Is Edit Mode" by using the "Insert reference" button and selecting them under "Common".

 

 

8) Click Save - and that's it. Now you can deploy your form, and make your users a little bit happier love.png
I hope you find this helpful - happy Nintexing to all of you grin.png
 
Curious about the code, but don't want to bother downloading it? Here it is for easy access:
 

var Filter = function (NFselectorControl, NFfilterControl) {
    this.selectorElement = NWF$('#' + NFselectorControl);
    this.filterElement = NWF$('#' + NFfilterControl);

    // The value of the last used filter on the current item is actually stored - we don't want that to be shown, so we clear the field.
    this.filterElement.val("");

    // We only want the filter to be applied after a certain timeout - due to performance. This variable is used to control this.
    this.timeout;

    // Set up the GUI: When filter value is changed, apply the filter...
    this.setupEventHandler(this);
};

Filter.prototype.setupEventHandler = function (object) {

    // Apply the filter when the user inputs something - but wait until a second has passed from the last key stroke.
    this.filterElement.bind("input", function (event) {
        clearTimeout(object.timeout);

        object.timeout = setTimeout(function () {
            var waitDialog = SP.UI.ModalDialog.showWaitScreenWithNoClose(' ', 'Please wait...', 110, 280);
            setTimeout(function () {
                object.applyFilter(object);
                waitDialog.close();
            });

        }, 1000);
     });

    // The value of the selector may have changed due to the filtering. In order to get the new value stored, it is necessary to put the value of the HTML SELECT into the Nintex selector container.
    // See https://community.nintex.com/thread/7059 for more info on this issue.
     this.selectorElement.change(function () {
        var value = NWF$(this).val();
        object.selectorElement.parent().find("input").val(value);
    })
}

Filter.prototype.applyFilter = function (object) {
    // Get the value of the FILTER element.
    var filterValue = object.filterElement.val().toLowerCase();

    // Run through all descendants of the selector that are OPTION elements...
    object.selectorElement.find("OPTION").each(function () {

// NOTE: From v2.9.0.3 the above line must be replaced with:

// object.selectorElement.parent().children(0).find("OPTION").each(function () {

// This is due to changes in Nintex' way to implent the dropdowns.


    var optionValue = NWF$(this).text();

    // If they qualify, and have SPAN as parent, then make them direct children of the SELECT by removing the surrounding SPAN.
    if (optionValue.toLowerCase().indexOf(filterValue) > -1) {
        if (NWF$(this).parent().is("SPAN")) {
            NWF$(this).unwrap();
        }
    }

    // If they do not qualify, and do not have SPAN as parent, then put a SPAN around the element.
    if (optionValue.toLowerCase().indexOf(filterValue) == -1) {
        if (!NWF$(this).parent().is("SPAN")) {
            NWF$(this).wrap("SPAN");
        }
    }
});

    // Make Nintex take notice that the value of the selector may have changed.
    object.selectorElement.trigger("change");
};

 

Update March 1st 2017: Due to changes in Nintex' implementation of the dropdown, a small change has been made to the script. If you are running Nintex Forms v 2.9.3 or newer, then please download and use the NF-OptionsFilter-forms-v2.9.3.0.zip file. Thank you Oliver Schneider‌ for making me aware of this issue.


17 replies

Userlevel 4
Badge +11

Hi Leif Frederiksen‌, 

that's great!! Why don't you post/link it also on  so it could be easier for other users to find such a valuable resource?

Giacomo 

Userlevel 7
Badge +17

Yes, put this on the Xchange! Keep blogging, you have great innovation and scripting skills!

Userlevel 5
Badge +12

This is one for the bookmarks.  Excellent work!

Badge +4

Hi,

there seems to be a problem.

I tried this code on my productive System and it works fine (thank you!) But on the development System it doesn't work.

I had a look at the code of the Website and figured out - there are no <option> tags anyway.

Maybe someone from Nintex have a clue. I use Nintex and Forms 2013 with SharePoint Foundation. My productive System have Version Nintex 3.1.7.10 and Forms 2.9.0.0

The development have Nintex 3.2.1.0 and Forms 2.9.4.0

Are there any changes in the Forms?

Thank you.

Userlevel 4
Badge +11

Hi Oliver Schneider‌,

looking at Nintex Forms 2013 - Release Notes‌ for versions later than your production one there have been a change in lookup control (version 2.9.2.0) and all version from 2.9.3.0 have 

Important information

  • This release includes changes to behaviours of some controls. The changes may require adjustments to custom JavaScript.

So it could be that some of these version have changed how the list lookup control is rendered in the page..

I don't have currently an environment with one of these versions installed, maybe Leif Frederiksen‌ or someone else here on the community could check it and find how to update the javascript for newer Forms version

Badge +7

Thank you for making me aware of this. I got the same problem after a recent update. Fortunately my users have not discovered it yet

A quick fix here: change the following line in the script:

object.selectorElement.find("OPTION").each(function () {

to this:

object.selectorElement.parent().children(0).find("OPTION").each(function () {

I am not quite happy with this fix - it seems kind of shaky and something that might break again soon when Nintex finds it convenient to change the implementation.

The question that we actually need an answer to is this:

How do I get the element that carries my OPTIONS from the element that my "Client ID JavaScript variable name" points to in a stable and predictable way? 

Prior to the update it was this element itself, but now it is "the parents first child". Please advice a better, stable and predictable way to get the options.

I some of you guys and gals have input on this, then don't hesitate to share

Regards

Leif

Badge +4

Hi Leif,

you're welcome ;-)

I tried to fix this issue for my own, but my JS is not quiet good. Thank you for your update.

Now I have to test if it works with my lists (more then 18000 Elements)... I think it will take a few "seconds" for the script to hide all the entries.

Regards

Oliver

Edit:

As expected - it works fine but it takes 3:20 minutes to filter all 18000 Elements... Way too long for such a dataload. Thank you anyway for your help...

Anyone having issues selecting the first item in the filtered list?  The filtering works great but the first value cannot be assigned to a field.  Any suggestions?

Badge +1

I am also having the same issue. The value of the default/first item in the filtered field has a value of a empty string. 

Badge +1

I'm probably missing something, but the only way I could get around this issue was to ensure that the "Please select a value..." option doesn't get filtered out. 

e.g.

if (optionValue.toLowerCase().indexOf(filterValue) == -1 && optionValue != "Please select a value...")

Badge +1

If I understand this correctly JS will search from the items loaded in dropdown. In my case there are more than 50000 suppliers which need to bind to list lookup, once I bind these many items its not showing any of the item other than "Please select a value" in dropdown.

Can somebody help on this. Its urgent.

Thanks

Badge +4

Hi Swapnil Bhogale,

I had a similar Problem with the amount of data. Perhaps you can use a few hints that I figured out in my description:

CAML-Query Dropdowns

Badge +1

Thanks Oliver Schneider, Your solution worked like champ.

Badge +5

Hello Leif Frederiksen‌ - I would be very grateful if you could tell me how to adapt this for when the lookup field is multiple choice rather than a dropdown?

Hi Leif, thank you for the solution to this! 


It works however, there are times when the dropdown list gets ‘disabled’/grayed out and I am unable to enable it despite removing everything from the filter.



Is there something I can add to the JS to disable the attribute or on the change event?


 


Thank you in advance 

Badge +2
Hi, I have tried the code but I'm getting error in new Filter(varReply, varReplyFilter) saying Filter is undefine? any changes to this?

 


 NWF$(document).ready(function(){
        if (Is New Mode || Is Edit Mode) {
            new Filter(varReply, varReplyFilter);
        }
  });

Badge +1

Leif Frederiksen‌, How does your solution work for Check Boxes (Multiple-Selection). It works for other options fine except for check boxes. Is there a way to make it work. I would appreciate if anyone can help in this regard.


 


Thanks


 



 

Reply