kelliganp
Scholar

Auto-populating Rows in a Repeating Section

Jump to solution

Hi Folks,

 

I have a form with a repeating section and I want the user to input a code (DoDIC) then get a filtered selection of national stock numbers (NSN). Once the user selects an NSN, I want several single line text (SLT) controls to populate from the NSN catalog list. Additionally, I want some of the SLT controls to populate with a calculated value after the "Rounds" (quantity) field is filled in with an integer. These calculated values are "Dollar Value" based on the unit price from the catalog, and the "Short Tons" (STON) based on the STON from the catalog. I have the repeating section working for the first row, but when another row is added, and an NSN is selected, the fields for the second and any subsequent rows do not auto-populate.

 

To populate the controls, I am using calculated value (CV) controls with a lookup formula as seen in the two screen-shots below...

Screen Shot 001.pngScreen Shot 002.png

My js code look like this...

 

NWF$(function() {
NWF$('#'+ jsvar_TARF1NSNLookup_LLU).on('change', function()
    {
        setTimeout(function() {
            if (NWF$('#'+ jsvar_TARF1Nomenclature_CAL).val())
            {
                NWF$('#'+ jsvar_TARF1Nomenclature_TXT).val(NWF$('#'+ jsvar_TARF1Nomenclature_CAL).val());
                NWF$('#'+ jsvar_TARF1USGDesc_TXT).val(NWF$('#'+ jsvar_TARF1USGDesc_CAL).val());
                NWF$('#'+ jsvar_TARF1STON_TXT).val(NWF$('#'+ jsvar_TARF1STON_CAL).val()*NWF$('#'+ jsvar_TARF1Rounds_INT).val());
                NWF$('#'+ jsvar_TARF1DollarValue_CUR).val(NWF$('#'+ jsvar_TARF1Price_CAL).val()*NWF$('#'+ jsvar_TARF1Rounds_INT).val());
			}
		},2000);
	});
});

 

I realize it is incomplete with regards to all of the calculations that are based on the number rounds input but while testing I ran into this issue and thought it a priority to find out if this is even possible before I finished the code. Here is a screenshot of a test input that failed to populate the second row.

Screen Shot 003.png

 

Calling on some past Nintex Heroes to see if they can respond!  @MegaJerk@nico@TomaszPoszytek@cassymfreeman@SimonMuntz@mlauer

Any assistance with this would be greatly appreciated!

 

Thanks and Kind Regards,

Patrick

0 Kudos
Reply
6 Replies
MegaJerk
Collaborator

Re: Auto-populating Rows in a Repeating Section

Jump to solution

I never saw a notification for being tagged in this thread, but I happened upon it nevertheless.

 

The reason I think that your code isn't working is twofold. 

 

Reason Number 1

Is because using the Form Control's JavaScript named ID variable that you set in a Control's Settings, simply doesn't work well with any Control that is within a Repeating Section. This is in part because an ID in the spec of HTML is considered a unique value. So, while the *first* instance of a control in a Repeating Section will have that ID, every control created when a new row has been added will have its own unique ID because an ID can only ever reference a single element.

 

Because of this, a form can be considered to have different levels of "Context". Repeating Section Rows are considered their own 'context' from the rest of the form outside of the Repeating Section Control proper. While all of this is typically kept away from you as a form creator, it's important to understand as you do more complex things with Forms.

 

My suggestion for working with Form Controls (in general, not just for Repeating Sections) is to use the Control's Name instead. Ideally you should be naming your controls with unique and useful names, and you can use those names to target the controls of any particular Context, which is far more useful and typically more correct. 

 

Reason Number 2

While you apply your "On Change" event handler to the target control in a new / existing form that has only one row, it never is applied to any of the controls in the rows that are created after it! In fact it would never be applied to any of the target controls outside of the control in the first row because it is using the ID of only that control.

 

Instead you must not only target the control in any existing row at the start of the form load, but you must then also use a built in Form Event ("RegisterRepeaterRowAdded") to target the control in any subsequent rows that are generated during use (please see my community post about Nintex Form Events here https://community.nintex.com/t5/Community-blogs/The-Big-Event-A-Closer-Look-At-Nintex-Form-Events/ba... to learn more) 

 

Possible Solution

I have worked up the following code without actually opening a form, mainly because you have a lot going on in yours and working up a full on mockup with dummy data would be difficult without a lot more time and information. That said I have tried to be as thorough as I can be with the explanation in how it works using the comments. You should be able to paste this code into the Custom Javascript section of your Form (in settings) and with a few tweaks to things like Control Names, should be able to get it working. 

 

Also, there are several "helper" functions that are included with this that are just parts of a greater body of work that I use for my own forms. While they are not commented as thoroughly, their nature is pretty straight forward. That said, it does add to the general "busy" look of the code, but makes the important code that handles things proper a lot cleaner looking.  

 

That said if you have more questions or issues, let me know and I can work them out given enough info. 

 

The code is as follows:

 

/* -------------------------------- */
/* -------------------------------- */
/* ==== HELPER FUNCTIONS START ==== */
/* -------------------------------- */
/* -------------------------------- */

/*
	This function takes a ControlName (string) and sourceContext, 
	and returns the value(s) of any controls of matching name.

	The returned value's TYPE will change based on how the Control
	is setup, but can be forced to be a string if you set the third
	argument to true.
*/
var getControlValueByName = function (controlName, sourceContext, getValueAsString) {
	if (getValueAsString) {
		getValueAsString = "string2";
	}

	sourceContext = (sourceContext || NWF$(document));

	var targetFormControlID = sourceContext.find("[data-controlname='" + controlName + "']").attr("formcontrolid");
	NWF.FormFiller.Functions.GetValueContextCache(sourceContext)[targetFormControlID] = undefined;
	var rawValue = NWF.FormFiller.Functions.GetValue(targetFormControlID, sourceContext, getValueAsString);
	return rawValue;
};

/*
	This function takes a controlName (string) and sourceContext,
	and returns a jQuery object of any controls matching that name.

	The number of controls is limited to whether or not a proper
	sourceContext has been passed into the function.
*/
var getControlByName = function (controlName, sourceContext) {
	sourceContext = (sourceContext || NWF$(document));
	return sourceContext.find("[data-controlname='" + controlName + "']");			
};

/*
	This function takes a SLT control (jQuery Object), and a
	new Value to set the SLT control to.

	It will automatically force an update to the control to trigger
	any associated Rules to said control, but that behavior can be
	toggled by setting the third argument to false.
*/
var setSLT = function (txtControl, newValue, updateControl) {
	var innerControl = txtControl.find("input.nf-associated-control, textarea.nf-associated-control");
	var currentValue = innerControl.val();

	updateControl = updateControl !== false;

	if (typeof newValue !== "string" || !newValue) {
		return txtControl;
	}	

	if (innerControl.data("OldValue") !== currentValue) {
		innerControl.data("OldValue", currentValue);
	}

	if (updateControl) {
		innerControl.val(newValue).trigger("change");
	} else {
		innerControl.val(newValue);
	}		

	return txtControl;
};

/* -------------------------------- */
/* -------------------------------- */
/* ===== HELPER FUNCTIONS END ===== */
/* -------------------------------- */
/* -------------------------------- */

/* 
	This is the function that actually does the work of setting up the On Change event
	It requires a Repeating Section Row to function.
*/

var setNSNLookupEvent = function(repeaterRow){

	/* just making sure the repeaterRow is a jQuery object */
	repeaterRow = NWF$(repeaterRow);

	/* if we have just 1 row, then continue */
	if (repeaterRow.length === 1) {

		/* get the control named "llu_ProductionReportTARF1NSN" and handle it's on change event */
		getControlByName("llu_ProductionReportTARF1NSN", repeaterRow).on("change", function(){
			setTimeout(function() {

				/* get the value of the following controls */
				var calNomenclatureVal = getControlValueByName("TARF1Nomenclature_CAL", repeaterRow, true);
				var calDescVal = getControlValueByName("TARF1USGDesc_CAL", repeaterRow);
				var calStonVal = getControlValueByName("TARF1STON_CAL", repeaterRow);
				var calPriceVal = getControlValueByName("TARF1Price_CAL", repeaterRow);
				var calRoundsVal = getControlValueByName("TARF1Rounds_INT", repeaterRow);

				/* if the following control has a value then... */
				if (calNomenclatureVal){
					/* set the SLT values accordingly */			
					setSLT(getControlByName("TARF1Nomenclature_TXT", repeaterRow), calNomenclatureVal);
					setSLT(getControlByName("TARF1USGDesc_TXT", repeaterRow), calDescVal);
					setSLT(getControlByName("TARF1STON_TXT", repeaterRow), calStonVal * calRoundsVal);
					setSLT(getControlByName("TARF1DollarValue_CUR", repeaterRow), calPriceVal * calRoundsVal);             
				}
			},2000);
		});
	}	
};


/*
	This Form Event will run once all of the controls are ready to rock,
	but before the user has control
*/
NWF.FormFiller.Events.RegisterAfterReady(function () {
	/* PROVIDE YOUR RS CONTROL'S NAME IN THE CODE BELOW  */
	var targetRSControl = getControlByName("your_RS_ControlName_HERE");

	/*
		Because this code needs to work when you load a form
		that has already had Rows added to its RS, we grab all
		of the visible rows of the RS
	*/

	/*
		NOTE: notice how I have to break up the "not" portion of that selector statement?
		that's because Nintex Forms has a runtime function called "not", and it will
		attempt to replace the word "not" followed by an open parens with that built in
		runtime function. That's not what we want, so I have to keep the open paren
		away from the keyword. This is a quirk of working with js directly in the form!
	*/
	var visibleRows = targetRSControl.find(".nf-repeater-row:not" + "(.nf-repeater-row-hidden)");

	/* for every visible (existing) row... */
	visibleRows.each(function(index, row){
		/* apply the event handler */
		setNSNLookupEvent(NWF$(row));
	});
});

/*
	Last but not least, this is reason number 2 why your code wasn't working.
	Every time you add a new row, it gets created without the above event
	handler ever knowing it exists because that code has already run!

	So, every time there is a new row added, we need to add that event
	handler to the target control in the new row.

	Every time a new row is added to a form, the code responsible for
	created that new row invokes anything you've added to the
	RegisterRepeaterRowAdded form event.

	So by adding the below function to that registry, it will be invoked
	every time you create a new row!
*/
NWF.FormFiller.Events.RegisterRepeaterRowAdded(function (thisRow) {
	setNSNLookupEvent(thisRow);
});

 

 

Reply
kelliganp
Scholar

Re: Auto-populating Rows in a Repeating Section

Jump to solution

Hi @MegaJerk ,

 

Sorry for the slow response. I have been tied up in travel. I made the requisite adjustments to the control names and got the code mostly working. The Nomenclature and USG Desc controls populate in the repeating rows. As seen in the image below, the Short Ton (STONs) and Dollar Value controls that are calculated based on the multiplier in the Rounds control do not populate. It is worth noting that the round count may be entered before the NSN is selected or after depending on the user. One additional wrench in the works is the in addition to "TARF I" part of this form with its repeating section, there will also be a separate "TARF II" part that will need identical functionality. How would this be done with the driest code possible? The naming of objects will be tightly similar except, for example, instead of "cv_TARF1Nomenclature", the name of this control will be "cv_TARF2Nomenclature". Finally, I find your code solution very interesting but as someone that does not do a great deal JS work, it is a bit over my head. I would love to sit down and discus your solution over a video/screen-share if you are willing.

Screen Shot 004.png

Here is the code as I have it now.

/* -------------------------------- */
/* -------------------------------- */
/* ==== HELPER FUNCTIONS START ==== */
/* -------------------------------- */
/* -------------------------------- */

/*
	This 'function expression' takes a ControlName (string) and sourceContext, 
	and returns the value(s) of any controls of matching name.

	The returned value's TYPE will change based on how the Control
	is setup, but can be forced to be a string if you set the third
	argument to true.
*/
var getControlValueByName = function (controlName, sourceContext, getValueAsString) {
	if (getValueAsString) {
		getValueAsString = "string2";
	}

	sourceContext = (sourceContext || NWF$(document));

	var targetFormControlID = sourceContext.find("[data-controlname='" + controlName + "']").attr("formcontrolid");
	NWF.FormFiller.Functions.GetValueContextCache(sourceContext)[targetFormControlID] = undefined;
	var rawValue = NWF.FormFiller.Functions.GetValue(targetFormControlID, sourceContext, getValueAsString);
	return rawValue;
};

/*
	This 'function expression' takes a controlName (string) and sourceContext,
	and returns a jQuery object of any controls matching that name.

	The number of controls is limited to whether or not a proper
	sourceContext has been passed into the function.
*/
var getControlByName = function (controlName, sourceContext) {
	sourceContext = (sourceContext || NWF$(document));
	return sourceContext.find("[data-controlname='" + controlName + "']");			
};

/*
	This 'function expression' takes a SLT control (jQuery Object), and a
	new Value to set the SLT control to.

	It will automatically force an update to the control to trigger
	any associated Rules to said control, but that behavior can be
	toggled by setting the third argument to false.
*/
var setSLT = function (txtControl, newValue, updateControl) {
	var innerControl = txtControl.find("input.nf-associated-control, textarea.nf-associated-control");
	var currentValue = innerControl.val();

	updateControl = updateControl !== false;

	if (typeof newValue !== "string" || !newValue) {
		return txtControl;
	}	

	if (innerControl.data("OldValue") !== currentValue) {
		innerControl.data("OldValue", currentValue);
	}

	if (updateControl) {
		innerControl.val(newValue).trigger("change");
	} else {
		innerControl.val(newValue);
	}		

	return txtControl;
};

/* -------------------------------- */
/* -------------------------------- */
/* ===== HELPER FUNCTIONS END ===== */
/* -------------------------------- */
/* -------------------------------- */

/* 
	This is the function that actually does the work of setting up the On Change event
	It requires a Repeating Section Row to function.
*/

var setNSNLookupEvent = function(repeaterRow){

	/* just making sure the repeaterRow is a jQuery object */
	repeaterRow = NWF$(repeaterRow);

	/* if we have just 1 row, then continue */
	if (repeaterRow.length === 1) {

		/* get the control named "llu_ProductionReportTARF1NSN" and handle it's on change event */
		getControlByName("llu_ProductionReportTARF1NSN", repeaterRow).on("change", function(){
			setTimeout(function() {

				/* get the value of the following controls */
				var calNomenclatureVal = getControlValueByName("cv_TARF1Nomenclature", repeaterRow, true);
				var calDescVal = getControlValueByName("cv_TARF1USGDesc", repeaterRow);
				var calStonVal = getControlValueByName("cv_TARF1STON", repeaterRow);
				var calPriceVal = getControlValueByName("cv_TARF1Price", repeaterRow);
				var calRoundsVal = getControlValueByName("slt_ProductionReportTARF1Rounds", repeaterRow);

				/* if the following control has a value then... */
				if (calNomenclatureVal){
					/* set the SLT values accordingly */			
					setSLT(getControlByName("slt_ProductionReportTARF1Nomenclature", repeaterRow), calNomenclatureVal);
					setSLT(getControlByName("slt_ProductionReportTARF1USGDesc", repeaterRow), calDescVal);
					setSLT(getControlByName("slt_ProductionReportTARF1STON", repeaterRow), calStonVal * calRoundsVal);
					setSLT(getControlByName("slt_ProductionReportTARF1DollarValue", repeaterRow), calPriceVal * calRoundsVal);             
				}
			},2000);
		});
	}	
};


/*
	This Form Event will run once all of the controls are ready to rock,
	but before the user has control
*/
NWF.FormFiller.Events.RegisterAfterReady(function () {
	/* PROVIDE YOUR RS CONTROL'S NAME IN THE CODE BELOW  */
	var targetRSControl = getControlByName("rpt_TARF1ProductionReport");

	/*
		Because this code needs to work when you load a form
		that has already had Rows added to its RS, we grab all
		of the visible rows of the RS
	*/

	/*
		NOTE: notice how I have to break up the "not" portion of that selector statement?
		that's because Nintex Forms has a runtime function called "not", and it will
		attempt to replace the word "not" followed by an open parens with that built in
		runtime function. That's not what we want, so I have to keep the open paren
		away from the keyword. This is a quirk of working with js directly in the form!
	*/
	var visibleRows = targetRSControl.find(".nf-repeater-row:not" + "(.nf-repeater-row-hidden)");

	/* for every visible (existing) row... */
	visibleRows.each(function(index, row){
		/* apply the event handler */
		setNSNLookupEvent(NWF$(row));
	});
});

/*
	Last but not least, this is reason number 2 why your code wasn't working.
	Every time you add a new row, it gets created without the above event
	handler ever knowing it exists because that code has already run!

	So, every time there is a new row added, we need to add that event
	handler to the target control in the new row.

	Every time a new row is added to a form, the code responsible for
	created that new row invokes anything you've added to the
	RegisterRepeaterRowAdded form event.

	So by adding the below function to that registry, it will be invoked
	every time you create a new row!
*/
NWF.FormFiller.Events.RegisterRepeaterRowAdded(function (thisRow) {
	setNSNLookupEvent(thisRow);
});

 

Thanks again! I really appreciate your willingness to assist and your expertise!

Kind Regards,

Patrick Kelligan

0 Kudos
Reply
kelliganp
Scholar

Re: Auto-populating Rows in a Repeating Section

Jump to solution

Hi @MegaJerk ,

 

With the assistance of a colleague, @espinozae, we got the final controls to populate/calculate. Thanks so much for the code assistance. You are a ROCK STAR!

Here is the final code with @espinozae's contribution.

/* -------------------------------- */
/* -------------------------------- */
/* ==== HELPER FUNCTIONS START ==== */
/* -------------------------------- */
/* -------------------------------- */

/*
	This 'function expression' takes a ControlName (string) and sourceContext, 
	and returns the value(s) of any controls of matching name.

	The returned value's TYPE will change based on how the Control
	is setup, but can be forced to be a string if you set the third
	argument to true.
*/
var getControlValueByName = function (controlName, sourceContext, getValueAsString) {
	if (getValueAsString) {
		getValueAsString = "string2";
	}

	sourceContext = (sourceContext || NWF$(document));

	var targetFormControlID = sourceContext.find("[data-controlname='" + controlName + "']").attr("formcontrolid");
	NWF.FormFiller.Functions.GetValueContextCache(sourceContext)[targetFormControlID] = undefined;
	var rawValue = NWF.FormFiller.Functions.GetValue(targetFormControlID, sourceContext, getValueAsString);
	return rawValue;
};

/*
	This 'function expression' takes a controlName (string) and sourceContext,
	and returns a jQuery object of any controls matching that name.

	The number of controls is limited to whether or not a proper
	sourceContext has been passed into the function.
*/
var getControlByName = function (controlName, sourceContext) {
	sourceContext = (sourceContext || NWF$(document));
	return sourceContext.find("[data-controlname='" + controlName + "']");			
};

/*
	This 'function expression' takes a SLT control (jQuery Object), and a
	new Value to set the SLT control to.

	It will automatically force an update to the control to trigger
	any associated Rules to said control, but that behavior can be
	toggled by setting the third argument to false.
*/
var setSLT = function (txtControl, newValue, updateControl) {
	var innerControl = txtControl.find("input.nf-associated-control, textarea.nf-associated-control");
	var currentValue = innerControl.val();

	updateControl = updateControl !== false;

	if (typeof newValue !== "string" || !newValue) {
		return txtControl;
	}	

	if (innerControl.data("OldValue") !== currentValue) {
		innerControl.data("OldValue", currentValue);
	}

	if (updateControl) {
		innerControl.val(newValue).trigger("change");
	} else {
		innerControl.val(newValue);
	}		

	return txtControl;
};

/* -------------------------------- */
/* -------------------------------- */
/* ===== HELPER FUNCTIONS END ===== */
/* -------------------------------- */
/* -------------------------------- */

/* 
	This is the function that actually does the work of setting up the On Change event
	It requires a Repeating Section Row to function.
*/

var setNSNLookupEvent = function(repeaterRow){

	/* just making sure the repeaterRow is a jQuery object */
	repeaterRow = NWF$(repeaterRow);

	/* if we have just 1 row, then continue */
	if (repeaterRow.length === 1) {

		/* get the control named "llu_ProductionReportTARF1NSN" and handle it's on change event */
		getControlByName("llu_ProductionReportTARF1NSN", repeaterRow).on("change", function(){
			setTimeout(function() {

				/* get the value of the following controls */
				var calNomenclatureVal = getControlValueByName("cv_TARF1Nomenclature", repeaterRow, true);
				var calDescVal = getControlValueByName("cv_TARF1USGDesc", repeaterRow);
				var calStonVal = getControlValueByName("cv_TARF1STON", repeaterRow);
				var calPriceVal = getControlValueByName("cv_TARF1Price", repeaterRow);
				var calRoundsVal = getControlValueByName("slt_ProductionReportTARF1Rounds", repeaterRow);

				/* if the following control has a value then... */
				if (calNomenclatureVal){
					/* set the SLT values accordingly */			
					setSLT(getControlByName("slt_ProductionReportTARF1Nomenclature", repeaterRow), calNomenclatureVal);
					setSLT(getControlByName("slt_ProductionReportTARF1USGDesc", repeaterRow), calDescVal);
					setSLT(getControlByName("slt_ProductionReportTARF1STON", repeaterRow), calStonVal * calRoundsVal);
					setSLT(getControlByName("slt_ProductionReportTARF1DollarValue", repeaterRow), calPriceVal * calRoundsVal);             
				}
			},2000);
		});


		/* EUDORO  NEW NEW NEW START*/

		getControlByName("slt_ProductionReportTARF1Rounds", repeaterRow).on("change", function(){
			setTimeout(function() {
				/* get the value of the following controls */ 
				var calNomenclatureVal = getControlValueByName("cv_TARF1Nomenclature", repeaterRow, true); 
				var calDescVal = getControlValueByName("cv_TARF1USGDesc", repeaterRow); 
				var calStonVal = getControlValueByName("cv_TARF1STON", repeaterRow); 
				var calPriceVal = getControlValueByName("cv_TARF1Price", repeaterRow); 
				var calRoundsVal = getControlValueByName("slt_ProductionReportTARF1Rounds", repeaterRow);

				/* if the following control has a value then... */ 
				if (calNomenclatureVal){
					setSLT(getControlByName("slt_ProductionReportTARF1STON", repeaterRow), String((calStonVal * calRoundsVal).toFixed(6))); 
					setSLT(getControlByName("slt_ProductionReportTARF1DollarValue", repeaterRow), String((calPriceVal * calRoundsVal).toFixed(2)));
				}
			},2000);
		});
		/* EUDORO  NEW NEW NEW END END END */



	}	
};


/*
	This Form Event will run once all of the controls are ready to rock,
	but before the user has control
*/
NWF.FormFiller.Events.RegisterAfterReady(function () {
	/* PROVIDE YOUR RS CONTROL'S NAME IN THE CODE BELOW  */
	var targetRSControl = getControlByName("rpt_TARF1ProductionReport");

	/*
		Because this code needs to work when you load a form
		that has already had Rows added to its RS, we grab all
		of the visible rows of the RS
	*/

	/*
		NOTE: notice how I have to break up the "not" portion of that selector statement?
		that's because Nintex Forms has a runtime function called "not", and it will
		attempt to replace the word "not" followed by an open parens with that built in
		runtime function. That's not what we want, so I have to keep the open paren
		away from the keyword. This is a quirk of working with js directly in the form!
	*/
	var visibleRows = targetRSControl.find(".nf-repeater-row:not" + "(.nf-repeater-row-hidden)");

	/* for every visible (existing) row... */
	visibleRows.each(function(index, row){
		/* apply the event handler */
		setNSNLookupEvent(NWF$(row));
	});
});

/*
	Last but not least, this is reason number 2 why your code wasn't working.
	Every time you add a new row, it gets created without the above event
	handler ever knowing it exists because that code has already run!

	So, every time there is a new row added, we need to add that event
	handler to the target control in the new row.

	Every time a new row is added to a form, the code responsible for
	created that new row invokes anything you've added to the
	RegisterRepeaterRowAdded form event.

	So by adding the below function to that registry, it will be invoked
	every time you create a new row!
*/
NWF.FormFiller.Events.RegisterRepeaterRowAdded(function (thisRow) {
	setNSNLookupEvent(thisRow);
});
0 Kudos
Reply
kelliganp
Scholar

Re: Auto-populating Rows in a Repeating Section

Jump to solution

Hi @MegaJerk

 

I am running into a few problems with some calculated value controls. They partially work but they are not refreshing properly.

Figure 1.

Screen Shot 005.png

The order of operation is as follows.

  1. A DoDIC is input
  2. The NSN dropdown is populated
  3. An NSN is selected, thereby populating the Nomenclature and USG Description fields
  4. The Hours and Rounds (of ammo) are input into their fields (order of this does not matter)
  5. Short Ton (STONs) and Dollar Value auto-fields populate/calculate in the repeating row (from JavaScript) while the "Total Rounds" and "Total Hours" populate outside (below) the repeating section (see figure 2 for the configuration of these controls) but the "Total STONs" and "Total Dollar Value" controls DO NOT calculate
  6. Click the Add New Row link
  7. "Total STONs" and "Total Dollar Value" controls NOW calculate with the first row's values
  8. Repeat steps 1 though 4
  9. Again, the STONs and Dollar Value fields populate in the repeating row while the "Total Rounds" and "Total Hours" sum correctly below the repeating section but the "Total STONs" and "Total Dollar Value" still show only the first row values and do not update with the new sum
  10. Click the Add New Row link
  11. Total STONs" and "Total Dollar Value" controls NOW calculate with the first and second row's values
  12. Rinse and repeat...

So, I believe I understand the fundamental problem but am unsure how to correct it. As I see it, the "Total STONs" and "Total Dollar Value" fields need an event of some sort to force them to refresh (like adding another row). The rounds and hours are working because they are only referencing a regular control that is manually populated (see figure 2)

Figure 2.

Screen Shot 006.png

 

The "Total STONs" and "Total Dollar Value" fields, on the other hand are referencing fields in the repeating section that are being populated by our JavaScript code. I suspect that this is where the break down is. I will guess that the manual input and leaving focus (onblur perhaps?) is an event that will force a refresh just like adding a new row but when the code updates a field, the calculated value controls do not recognize an event has happened. Is that close to the issue and is there a straight forward way to fix this?

 

Thanks!

Patrick

0 Kudos
Reply
MegaJerk
Collaborator

Re: Auto-populating Rows in a Repeating Section

Jump to solution

I think I see the issue. in my haste to write a function to update your SLT controls, I trigged the wrong event to "update" the control and everything down stream! 

 

Taking a peak at how Nintex sets up the initial event triggers for controls, you can see that inputs of type "text" (that is "input:text") invoke the ProcessOnChange function when the "blur" event has been triggered:

MegaJerk_0-1658979239440.png

 

I confirmed that when I changed the setSLT code from where it says:

innerControl.val(newValue).trigger("change");

to:

innerControl.val(newValue).trigger("blur");

it updated the Calculated Controls I had setup outside of a Repeating Section:

MegaJerk_1-1658979487452.png

 

MegaJerk_2-1658979494388.png

 

 

The new function is:

var setSLT = function (txtControl, newValue, updateControl) {
  var innerControl = txtControl.find("input.nf-associated-control, textarea.nf-associated-control");
  var currentValue = innerControl.val();

  updateControl = updateControl !== false;

  if (typeof newValue !== "string" || !newValue) {
    return txtControl;
  } 

  if (innerControl.data("OldValue") !== currentValue) {
    innerControl.data("OldValue", currentValue);
  }

  if (updateControl) {
    innerControl.val(newValue).trigger("blur");
  } else {
    innerControl.val(newValue);
  }   

  return txtControl;
};

 

 

Try updating your code and let me know if it works out! 

0 Kudos
Reply
kelliganp
Scholar

Re: Auto-populating Rows in a Repeating Section

Jump to solution

The "blur" event did it! Thanks @MegaJerk

I have another event in the same repeating sections to handle. Should I keep posting here since it is the same code sample or start another thread?

0 Kudos
Reply