Documentation of Changes To JavaScript for SP 2016 Forms 4.3.0.11


Userlevel 5
Badge +14

I recently upgraded to the newest version of Nintex for SharePoint 2016 in an attempt to see if it would correct a few other issues I was having, but failed to respect the fact that the Nintex Forms javascript code-base was updated... resulting in a LOT of broken things. 

This was totally my fault, but the frustration of trying to figure out what in the heck was changed and where has made me think that creating some type of community documentation of any found changes might be worth while. 

I know that the changes I'm listing here are not going to be useful / used by a lot of people, but if you happen to come across any changes in your own work, and subsequent workarounds / fixes, please share them here so that we can create some type of log. 

♥♥♥ If you're interested in seeing which changes are happening between version, and would like to make that a regular part of the patch notes, consider adding a few votes to my suggestion herePublish JavaScript Change Logs In Patch Notes, or Put Nintex Forms On Github! – Customer Feedback for Nintex ♥♥♥

I'll do my best to keep this organized. Instead of just listing the functions that have changed, I'd like to stick to listing the affected controls being that not all of this is relevant at any given time and controls are good way to gauge which things you should be concerned about / looking for, if needed. 

Please add your finds in the comments if you have any

Thank you!  

CLASSIC FORMS:


Controls:

Repeating Section

NWF.FormFiller.Functions.AddNewRepeaterRow: Added the code 

if (!isResponsive && NF.LookupHelper && NF.LookupHelper.AdjustCheckBoxRadioButtonListHeight) {
  NF.LookupHelper.AdjustCheckBoxRadioButtonListHeight(newRepeaterRow);
} else if (!isResponsive && !NF.LookupHelper) {
  NF.BaseDataAccessHelper.AdjustCheckBoxRadioButtonListHeight(newRepeaterRow);
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍


It does not have error handling in the event that NF.BaseDataAccessHelper is undefined! Error results in Row not being added correctly. 

(In my environment, it the NF object exists, but BaseDataAccessHelper is never created / initialized anywhere...

(Edit (12/8/2017 11:38am EST): as soon as I posted this... it has since started generating... Nothing has changed, but now it works... because.)

(Edit (12/8/2017 7:06pm EST): Looks like I'm still having a LOT of trouble with getting this resource to load correctly. For whatever reason, it will be called and loaded in my main form, but I have not gotten it to automatically work on any other Nintex Form on the site. 

Because of this I have had to create a workaround that I can throw at the beginning of every form's JS to ensure that the NF namespace is being populated with the things it needs to make Repeating Sections work. It is as follows: 

if (NF.BaseDataAccessHelper === undefined) {
    NWF$.getScript(_spPageContextInfo.siteAbsoluteUrl.replace(/sites.+/, "") +
      _spPageContextInfo.layoutsUrl +
      "/NintexForms/JavaScriptStringHandler.ashx?" +
      "resourceType=jsfile&" +
      "fileName=NF.BaseDataAccessHelper.js&" +
      "culture=" +
      _spPageContextInfo.currentCultureName);
  }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I tried to make it as universal / generic as I could in the event someone else runs into this issue... bleh. ) 

----------------------------------------------------------------------------------------------------------------------------------

The line: 

NWF.FormFiller.Functions.RepositionAndResizeOtherControlsAndFillerContainerHeight(currentControl, heightIncrease, heightIncrease, formFillerDivCurrent);‍‍‍‍‍‍


Has been changed to: 

NWF.FormFiller.Resize.RepositionAndResizeOtherControlsAndFillerContainerHeight(currentControl, heightIncrease, heightIncrease, formFillerDivCurrent);‍‍‍‍‍‍


subsequently, you will need to change any calls to RepositionAndResizeOtherControlsAndFillerContainerHeight from the old way 'NWF.FormFiller.Function..." to "NWF.FormFiller.Resize...."

----------------------------------------------------------------------------------------------------------------------------------

Calculated Control


Calculated Controls received an update to when they are actually updated. In previous versions (4.2.2.0 guaranteed) , you could return a value from an Immediately Invoke Function Expression (see: IIFE - Glossary | MDN ), and the return value would be used to update the Calculated Control. 

This has since been changed (though I do not know precisely which version after 4.2.2.0 it occurred), and now the function that handles updating the control (NWF.FormFiller.Functions.ProcessCalculation) includes a few checks to make sure that the control is not inside of a repeating row section that is still hidden, and that the target control has some jQuery data attached to it called "GetControl". 

An example of what used to work: 

// Old
(function (sourceContext, rowIDClass) { 

  // Get the Calc Control's Value
  var rowIDValue = sourceContext.find("." + rowIDClass + " input").val();

  // If Control has no value...
  if (!rowIDValue) {

    // Create a new value of "Hello World"
    rowIDValue = "Hello World";

    // Notify what the new value will be.
    alert("setting Control's Value to: " + rowIDValue);
  }
 
  // Returned the value, and watch it be applied
  return rowIDValue;
}(sourceContext, "internalRow"))‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍


However, using that code now will result in the alter showing (3) times before the value is actually set. 

You'll need to change your code to something like this, to ensure that you are only doing things once:

// New
(function (sourceContext, rowIDClass) { 

  // Get the Calc Control's Value
  var rowIDValue = sourceContext.find("." + rowIDClass + " input").val();
 
  // Get the Topmost Div of our Calculated Control
  var resultControl = sourceContext.find("." + rowIDClass + ".nf-filler-control");
 
  // noControl = true if the .data("GetControl") is undefined
  var noControl = resultControl.data("GetControl") === undefined;

  // If our Calc Control is empty
  // And if noControl is **false** (meaning that
  // .data("GetControl") *does* exist)...
  if (!rowIDValue && !noControl) {
   
    // Create a new value of "Hello World"
    rowIDValue = "Hello World";

    // Notify what the new value will be.
    alert("setting Control's Value to: " + rowIDValue);
  }
 
  // Return either our populated value
  // or the original Calulated Control's Value
  // if noControl === true
  return rowIDValue;
}(sourceContext, "internalRow"))‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

This is particularly important if you're updating other Controls from within the formula of a Calculated Control! 

Calculated Controls that rely on other Calculated Controls, particularly the ones that reside inside of a Repeating Section, will ALSO be affected by this new change! 

Consider a sum() Calculated Control that sits inside of a Repeating Section's Row called Row Total, and a Calculation Control that sits on the Form proper called Section Total, which adds up the value of whatever each Row Total adds up to. 

When you add a new row, the Row Total Control inside of the Repeating Row will distribute it's undefined value out to the Section Total control. You could end up with a passed in array of something like "[300, 440,]" (notice the extra comma with no value behind it). Depending on how you are handling this data, it could lead to bad times. 

Be careful out there if you're rolling your own way of handling money! 

----------------------------------------------------------------------------------------------------------------------------------

Input Controls (Single Line Text & More):

 

The Event Handlers for all Input Controls that have the attribute type set to "text" have been changed and will require you to update any code that is pushing values to an input element if you want the change in value to be noticed by any Calculated Formula, Rule, or Script where that control has been referenced.

The way events were attached to input controls in version 4.2.2.0 is as this truncated example shows: 

// Old Version (4.2.2.0) from FormFiller.js, Copyright Nintex,
// but modified / truncated for clarity
NWF.FormFiller.Functions = function() {

  var formFillerDivCurrent = NWF$("#formFillerDiv");

  return {
    AttachOnChangeEvents: function(formFillerDivCurrent) {
     
      // Input:Text Handled Here!!!
      formFillerDivCurrent.on('blur', 'input:text', function(event) {
        NWF.FormFiller.Functions.ResetCircularReferenceRelatedVariables();
        NWF.FormFiller.Functions.ProcessOnChange(NWF$(this));
      });
      formFillerDivCurrent.on('change', 'input:radio', function(event) {
        NWF.FormFiller.Functions.ResetCircularReferenceRelatedVariables();
        NWF.FormFiller.Functions.ProcessOnChange(NWF$(this));
      });
      formFillerDivCurrent.on('change', 'input:checkbox', function(event) {
        NWF.FormFiller.Functions.ResetCircularReferenceRelatedVariables();
        NWF.FormFiller.Functions.ProcessOnChange(NWF$(this));
      });
      formFillerDivCurrent.on('input propertychange blur change', 'textarea', function(event) {
        NWF.FormFiller.Functions.ResetCircularReferenceRelatedVariables();
        NWF.FormFiller.Functions.ProcessOnChange(NWF$(this));
      });
      formFillerDivCurrent.on('change', 'select', function(event) {
        NWF.FormFiller.Functions.ResetCircularReferenceRelatedVariables();
        NWF.FormFiller.Functions.ProcessOnChange(NWF$(this));
      });
    }
  };
};‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍


However. In version 4.3.0.11 the code has been changed to: 

// New Version (4.3.0.11) from FormFiller.js, Copyright Nintex,
// but modified / truncated for clarity
NWF.FormFiller.Functions = function() {

  var formFillerDivCurrent = NWF$("#formFillerDiv");

  return {
    AttachOnChangeEvents: function(formFillerDivCurrent) {

      // Input Text Handled Here!!!
      formFillerDivCurrent.on('focus', 'input:text', function(event) {
        NWF$(this).data("OldValue", this.value);
      });
      formFillerDivCurrent.on('focus', 'textarea', function(event) {
        NWF$(this).data("OldValue", this.value);
      });

      // Input Text ALSO Handled Here!!!
      formFillerDivCurrent.on('blur', 'input:text', function(event) {
        if (NWF$(this).data("OldValue") !== this.value) {
          NWF.FormFiller.Functions.ResetCircularReferenceRelatedVariables();
          NWF.FormFiller.Functions.ProcessOnChange(NWF$(this));
        }
      });
      formFillerDivCurrent.on('change', 'input:radio', function(event) {
        NWF.FormFiller.Functions.ResetCircularReferenceRelatedVariables();
        NWF.FormFiller.Functions.ProcessOnChange(NWF$(this));
      });
      formFillerDivCurrent.on('change', 'input:checkbox', function(event) {
        NWF.FormFiller.Functions.ResetCircularReferenceRelatedVariables();
        NWF.FormFiller.Functions.ProcessOnChange(NWF$(this));
      });
      formFillerDivCurrent.on('input propertychange blur change', 'textarea', function(event) {
        if (NWF$(this).data("OldValue") !== this.value) {
          NWF.FormFiller.Functions.ResetCircularReferenceRelatedVariables();
          NWF.FormFiller.Functions.ProcessOnChange(NWF$(this));
        }
      });
      formFillerDivCurrent.on('change', 'select', function(event) {
        NWF.FormFiller.Functions.ResetCircularReferenceRelatedVariables();
        NWF.FormFiller.Functions.ProcessOnChange(NWF$(this));
      });
    }
  };
};

 

As you can see from the new version, the blur event, when handled, will check the jQuery Data (see: jQuery.data()) Object's property of "OldValue" to compare it to the current value of the element. However, that Data Object is set in the newly introduced focus event handler, which will set the data property to the value present in the element at the moment of focus

This can cause problems if you are setting the value of an input in an unorthodox way (via a function, rule, or control formula) because without calling the focus on the element before altering its value, the 'OldValue' property will not be set, which could lead to the control being inaccurately handled (to the developer) during the blur event.

To correct for this change. Use the following example code to set your input text fields:

(function () {
  var inputControl = NWF$("#" + singleLineTextControlID);   
  inputControl.trigger("focus").val("").trigger("blur");
}())‍‍‍‍

This will...

First, trigger the focus event, setting the OldValue property to whatever is contained as the value of the input

Second, it will update the current value to whatever you'd like (whatever you put inside of the val("") function).

Third, will then trigger the blur event, which will compare the OldValue vs. the current (new) value, which will, if they are not equal, invoke the functions to update any dependent controls where this input is referenced. 

----------------------------------------------------------------------------------------------------------------------------------


11 replies

Userlevel 6
Badge +15

Thanks for posting this up,

‌ / ‌ -- who could we contact to suggest that Nintex come out with notes such as these for each release? Sudden JavaScript inconsistencies are never a fun time...

Userlevel 5
Badge +14

While some patch notes are better than none, having something a bit more comprehensive in terms of files / dependencies added and code that has changed (just like you'd expect from something like a Git repository / versioning control), would make sorting through certain changes infinitely easier. 

Granted this is totally niche, and I understand that. The Customer Feedback post (listed above) might just collect dust, but it's worth a shot to get some type of comprehensive change log between versions for both javascript and even css. 



Userlevel 6
Badge +13

Hi, I don't know whether the issue I'm experiencing is related to this, I have recently updated to the latest version of Nintex 2016 and seem to be experiencing some issues. 

I have a dropdown control and a text box that are concatenated in a calculated value. This calculated value is in turn used as a parameter in a SQL request control, that runs a stored procedure that returns, in effect, a free text search for the user. I then have a button that uses javascript to write the selected values into a text box (since the user can search more than once in the form so their selected values need to be held somewhere) and clears down the search box. This was working before, but now, the search box clears down but the calculated value (my concatenated search term) remains the same. As a result the SQL request control doesn't clear down (a behaviour I require).

There is no direct javascript code attached to the calculated value, but I didn't know whether this change in behaviour can be put down to the update as I'm sure it worked before. 

Is there a piece of javascript I can use to clear down the value of the calculated value (or force it to refresh and see that the search value is empty and therefore it's value should be "". Here's the formula

if(lessThan(length(ProductSearch),3),"",CompanyCode+" "+ProductSearch)

Userlevel 5
Badge +14

Just real quick. I was able to do a small test and confirm that something stupid is certainly happening when you have a Single Line Text Control that has a value which is being referenced and used inside of a Calculated Control. 

Specifically, the "blur" event is not being handled... but only sometimes... which doesn't make a lot of sense to me. 

Essentially, if I threw some stupid function in the Calc Control's formula that had a debugger; break (to trigger the developer debugger), everything would work as expected, however... removing that would result in it reverting back to a behavior that ignored the event!!!! GAH!

What has turned Nintex Forms into a Quantum Physicist's experiment? To heck if I know, but I'll report back to you when I find out something more concrete, just wanted to confirm that you're not crazy. 

Userlevel 6
Badge +13

Appreciate it. The project I've been on for the last 6 weeks has me headed in the direction of crazy, so it's reassuring I've not yet reached that stage.

Userlevel 5
Badge +14

I have updated the main post to show how things have changed between past versions of Nintex Forms for the events related to updating Input:text fields, which I believe should solve your problem. 

Essentially, your javascript button will need to be updated to clear the value out as shown in the following example: 

(function () {
  var inputControl = NWF$("#" + singleLineTextID);   
  inputControl.trigger("focus").val("").trigger("blur");
}())‍‍‍‍

See the main post for the reasons behind why this change is necessary. 

Userlevel 5
Badge +14

Did the workaround for updating an input field by way of manual javascript work for you? 

Userlevel 6
Badge +13

I did briefly try this, but couldn't get it to work, since then I've been moved onto other stuff, so not given it the required work. Thanks for the help though.

Userlevel 5
Badge +14

I see. Well, if in the future you'd like to go more in depth, feel free to do so. 

The end! 

Badge +2

Any update on you guys? Is there specific JS version compatible with Nintex 2016?

Userlevel 5
Badge +14

Any update on you guys? Is there specific JS version compatible with Nintex 2016?

 

I’m not sure what you’re trying to ask. JS Version compatibility is completely dependent on the JS Engine whatever environment it’s being ran in is using. So if you’re using Internet Explorer 6, you won’t have access to the same stuff like you would if you were to use Firefox or Chrome. 

 

If that’s not what you meant, please refine your question. 

Reply