List lookup filter completed event?


Badge +2

Hi  I have a form with cascading filtered list lookups.  Let's call then Lookup1 and Lookup2.  The selection in Lookup1 is used to filter the options in Lookup2.  Due to the way the underlying is organized (unfortunately, can't be changed), there will be duplicates in Lookup2 even after the filter is applied.  I have a JavaScript function to remove the duplicates.  However, it needs to execute after the filtering is complete.  I tried calling it in the 'change' event of Lookup1 but at that point, Lookup2 has no data in it.  I can call it on the 'click' event of Lookup2 but the duplicates are still visible until Lookup2 is clicked again (e.g. duplicates are removed after the list is displayed).  I need to be able to fire off the dup removal function as soon as the list has finished loading the filtered data.  Is there a way to do this?  Any help would be greatly appreciated!


11 replies

Badge +7

Have you tried calling it on the 'change' event of Lookup2, or does it not fire when Lookup1 changes the options in Lookup2?

Badge +2

I tried that.  It doesn't fire when the value in Lookup1 causes it to filter.

Userlevel 5
Badge +14

instead of javascript, use 'Source 'view' to filter out not wanted entries

 

 

 

Due to the way the underlying is organized (unfortunately, can't be changed), there will be duplicates in Lookup2 even after the filter is applied.

that's definitelly not a good design. change it as soon as you can, sooner or later it gets you into serious troubles.

if you have multiple entries with the same display text but different IDs for each, how can you know for sure which one is the one user can select and which ones are ones to be hidden???

note with lookup you do not select the display text (that's just something what's presented to users, and can be changed anytime) but in fact you select respective ID (key).

Badge +2

The source view is a SharePoint 2013 list and unfortunately doesn't have the ability to create a view with unique entries only.  I ended using 'setInterval' to run the dup removal function every second.  Not the ideal solution but it'll work until I can come up with something better.

 

I've been working on restructuring the data as best I can but I'm limited in how much I can do at this point.  If I ever get the chance to fix this list, I'll jump on it for sure!

 

Thanks for the help!

Userlevel 5
Badge +14

A few questions

Which version of Nintex Forms / SharePoint are you using? 

If On-Prem SP, which Forms 'Type' are you using? Classic or New? 

Badge +2

Nintex Forms 2013 Ver. 2.11.3.10

SharePoint 2013 On prem

Classic form

Userlevel 5
Badge +14

So, there is an event that fires when a Lookup Control has finished making the lookup and retrieved the values that it's going to use to populate the control. It's called "readystatechange" but it's not an event that can be handled via the DOM (I think), BUT because the backing lookup function will invoke any / all Formatting Rules on the given Control in question, you can setup a Rule that will allow you to capture this particular event! 

The following code is a rough boiler plate that has been scaled back from something I'm using. I have tried to comment as much as I can to explain what's happening at each step, but the part you should be concerned with is the portion that says "DO YOUR WORK HERE" :D 

 

It might be a huge pain in the but to debug in anything other than Chrome, but it is, as far as I know, the only way to properly "know" when your Lookup Control has pulled new values down (whether that's zero or more values, doesn't matter) because a filter changed. 

For a more indepth guide on what’s happening, please see my (on the previous forums – Blog) post: Breaking The Rules - A Dive Into The Nintex Forms Rule System

 

CODE: 

 

(function(formControlCall) {
  "use strict";
  /* default the return to false; */
  var returnValue = false;

  /* Check to see if the Form is even in Edit Mode */
  if ({Common:IsEditMode}) {

    /* If it is, then we'll setup the starting vars */ 
    var formControlID = formControlCall.split("'")[1] || "";
    var targetControl = sourceContext.find("[formcontrolid='" + formControlID + "'].nf-filler-control");
    var internalElement = targetControl.find("[formcontrolid='" + formControlID + "'].nf-associated-control");
    var selectElement = internalElement.siblings("select.nf-client-control");
    var isReadyStateChangeEvent = false;
    var doFormatting = false; 

    /* Some of this is just boilerplate that needs to exist based on how 
       Nintex Forms fires off Formatting Rules when a Form and Controls are
       first loaded. However, because the sevearl different versions of NF
       and the changes made to their codebase, it's difficult to know just
       how many of these things work the same across all versions. 

       If you feel like something isn't working for you, throw a debugger; 
       command into here and try to poke around and see what's happening
       in the developer console. */

    /* Let's make sure that there actually is a Select element in our Lookup */
    if (selectElement[0] !== undefined) {

      /* If there is, then no matter what, if the properties that track if the 
         Hide / Disable formatting rules have been activated do not exist, then we
         need to just go on and return 'true' so that those properties can get 
         setup! */
      if ((targetControl.data("DisableCounter") === undefined && targetControl.data("HideCounter") === undefined)) {
        doFormatting = true;
      }

      /* However, if those properties exist, we need to make sure that we're
         actually targeting a Lookup Form Control, so we test the control type id. */
      if (!doFormatting && targetControl.attr("data-formcontroltypeid") === "c0a89c70-0781-4bd4-8623-f73675005e15") {

        /* From there we need to know that the event isn't undefined */
        if (event !== undefined) {

          /* If it isn't, then we'll then look to see if it's a "readystatechange" event,
             which is invoked anytime that there is a change to the source / filter-where 
             value. This, specifically, is the event that you're looking to capture to
             see the options immediately after they have been populated by the filter!! */
          if (event.type === "readystatechange") {
            /* NOTE: Remember that you can set a variable in this Rule that will
            better indicate when you're in the readystatechange event type if you've
            reached this point, or you can just do your entire pruning work here I suppose...*/

            isReadyStateChangeEvent = true;

            /* The ReadyStateChange event can also fire when you make a new row.
               In those cases, it might just be initializing, but there won't be
               any available options, unless it's the first filter control */
            if ((event.srcElement && event.srcElement.text === undefined) || event.srcElement.text.toLowerCase() !== "add new row") {
              doFormatting = true;
            }

          /* This is invoked when you delete a row in a Repeating Section, but might not even be needed for you. 
             If you wanna get rid of the entire 'else if', you can (if you don't need it). */  
          } else if (event.type === "click" && NWF$(event.srcElement).hasClass("nf-repeater-deleterow-image")) {
            doFormatting = true;
          }
        }
      }

      /* Once we have established that the Control is in a state
         that requires us to do work on the Options or Disable
         the control (in the event that there are NO options or 
         just ONE option), we can do our work here! */ 
      if (doFormatting) {
        

        /**********************************************
          !!!!!!!!!!!!! DO YOUR WORK HERE!!!!!!!!!!!!!!
          
          You can prune out the options you want based
          on whatever criteria you have! 

        if (isReadyStateChangeEvent) {
          var availableOptions = selectElement.find("option");

          availableOptions.each(function(index, option){
            if (option.someThingThatYourLookingFor) {
              option.hide();
            }
          });
        }
        ***********************************************/

        /* Let's get a count of all the options into a variable */
        var optionsCount = selectElement.find("option").length;
        /* This might have to change to

        selectElement.find("option:visible").length 

        if you've hidden them as I have shown in the sudo-code above */

        /* Remember that the "Please select a value..." is an actual Option
           So that means if the optionsCount is less than 3, there is only 
           (1) valid selectable option. We can just select it automatically
           and then Disable the control later.

           If we're under 3 options... */
        if (optionsCount < 3) {
          /* select the last option available */
          NWF$(selectElement.find("option")[optionsCount - 1]).attr("selected", true);
        } 
        /* ...Otherwise just continue */

        /* Trigger a change event on the element to 
        start validation (if needed) */
        internalElement.trigger("change");

        /* And set the ReturnValue to the result of this 
        expression. If under 3 options, the Control will
        be Disabled / Hidden based on the Rule selections. */
        returnValue = optionsCount < 3;
      }
    }
  }
  return returnValue;
}("{Control:Self}"))

Additional Info: 

Your code will live in a Formatting Rule as highlighted: 

30i0A2262E6400080F8.png

Badge +2

This is excellent stuff!  Thank you!!!!

Badge +4
hi @MegaJerk I've read both the post above and the link to the elongated version and I have a question relating to the 'timing' of the form.

If I have a Nintex form and I change one variable on the form, what determines when that variable is available to be used and does this depend on the type of control/variable?

The examples I am using are:
1. a List Lookup or a Choice control which determines a formatting rule.
2. a calculated value which uses a DiffDays(date1, date2) and then displays the number of days as a calculated value as an integer via a single line text box on the same form.

The more general level question is "is the form live and if not, when does the calculation happen?"
Userlevel 5
Badge +14

Hey there @johnfriday13, that's an interesting question and I have a few more to ask in return so that I can better understand the context or what it is you're trying to do with the info, however, could we move this discussion to either a new Topic all together, or over to my larger thread about Form Events (Breaking The Rules: A Dive Into The Nintex Forms Rule System)? 

In this way we're not piggybacking off of a thread that has already been answered

If neither one of those options sound good, feel free to shoot me a PM. 

The best way I can answer your question ("is the form live and if not, when does the calculation happen?") is to say that once a form has loaded (and spins up the RegisterAfterReady event), any change that you make to a control will trigger a series of internal events that do the following in roughly this order:

 

  • Update the Control's value
  • Run any Rules that are associated to the Control
  • Update any formulas that are dependant on it's value
  • Run any Rules that are associated to those Controls (which were dependent)
  • etc... 

 

As to *when* they become available? well... it kinda depends on what that even means in your context. 

Let's talk in a different thread that is more appropriate. 

Additionally, I recommend that you check out my other blog: (The Big Event: A Closer Look At Nintex Form Events) as it might help shine some light onto the inner workings of certain events and handling. 

Badge +4

Thanks @MegaJerk I have printed off your Big event post and am working through it at the moment. If we could start another post that would be great, I will post it and tag you.

Reply