cancel
Showing results for 
Search instead for 
Did you mean: 
kelliganp
Nintex Newbie

Resize a Repeating Section After Hiding Panels inside the Section

Jump to solution

Hi Folks,

I am building a form with a repeating section that has two panels (aligned vertically). The first panel is visible by default. The second panel should only appear later in the approval process. My problem is that there is a great deal of whitespace visible when the second panel is hidden. I have seen some old posts where the request was made in the uservoice forum to add a resize feature.

 

Does anyone know of any way to accomplish this yet?

 

I have seen you, @MegaJerk, popping up in many of the repeating section posts and was hoping that you had some guidance for me. I will say at the outset that I am not strong in JS but with a little guidance, I can usually get posted code to work if JS is needed for this.

 

Thanks and Regards,

Patrick

Labels: (1)
0 Kudos
Reply
11 Replies
MegaJerk
Nintex Newbie

Re: Resize a Repeating Section After Hiding Panels inside the Section

Jump to solution

A few questions. 

1. Is this a Classic or Responsive Form? 

2. Can you provide a Screenshot of the Form in Design Mode and one in Edit Mode (usage mode) so that I can see explicitly how it's laid out? 


Warning. It will indeed require a lot of JavaScript, but because I have so much customer Repeating Section stuff happening in my world, it shouldn't be that difficult for me to find some easy to drop in code that will accomplish what you're looking to do (assuming it's similar enough to the things that I'm already doing! Smiley Wink

Let's get cookin! 

0 Kudos
Reply
kelliganp
Nintex Newbie

Re: Resize a Repeating Section After Hiding Panels inside the Section

Jump to solution

Hi @MegaJerk!

 

 Clasic Foms.

 

Here is the forms section in question in Design Mode:

Design Mode 20190809.png

...and here is a screenshot of the form in Edit mode qwith both panels visible:

Edit Mode Both 20190809.png

...and here is the edit mode with the second panel hidden.

Edit Mode One 20190809.png

 

Thanks so much for assisting with this!

Best Regards,

Patrick

 

 

0 Kudos
Reply
MegaJerk
Nintex Newbie

Re: Resize a Repeating Section After Hiding Panels inside the Section

Jump to solution

I realized that I had one more question that needs to be answered. 

Is the condition that would make the Panel Visible / Invisible something that happens in real time, or is it something that is set outside of the form (say, via a Workflow)?

In otherwords, when the Form is loaded, do I need to worry about only Showing or Hiding it there, or should I worry about Showing it and Hiding because someone selected something specific on a triggering Control in the same Form? 

 

 

0 Kudos
Reply
kelliganp
Nintex Newbie

Re: Resize a Repeating Section After Hiding Panels inside the Section

Jump to solution

Hi @MegaJerk

 

The condition would be a vlaue in a column of the list. We call it WorkflowState. It wiould be a value set by default on a new form (NEW_STATE), or by a workflow (PM_STATE, PURCHASE_STATE, HOLD_STATE, END_STATE, etc.). This is a supply/purchase request process and in the case of our form, we want the second panel that pertains to "Post Receipt" information to show up only after the request has been approved and the items are ready to be or have been ordered by the supply team.

 

Thanks!

Patrick

0 Kudos
Reply
MegaJerk
Nintex Newbie

Re: Resize a Repeating Section After Hiding Panels inside the Section

Jump to solution

This should be pretty straight forward, though I am unsure of how your process fully works, if you have information that you'd like to show on the form only AFTER a certain state has been reached, then the below solution should do the trick. 

 

The Setup 

 

image.png

 

My form has a Repeating Section, inside of which are Two Panels (named Panel 1 and Panel 2 respectively).

 

Panel 2 has been given a CSS Class of "ReceiptPanel": 

image.png

(Note: Do not forget to add this CSS rule as it is critical

 

Next to the Repeating Section is a Label Control (reading 'Current State:') and a Choice Control associated to a List Column that I have named WorkflowState. The Workflow State Control is set to Visible: Yes // Enabled: No! It is just to show which state the Column Value currently has in it! 

 

The List Column (WorkflowState) is setup in the following way: 

image.png

 

 

The Rules

 

There is only one (1) Rule, and it is a Formatting Rule on Panel 2:

 

image.png

 

The Rule should contain the following code: 

(function(workflowState){
  switch (workflowState) {
    case "State 1":
    case "State 2":
    case "State 3":
      return true;
    default:
      return false;
  }
}(WorkflowState));

(Note: at the BOTTOM of that code, the word "WorkflowState" should be replaced by the actual Reference to the List Column in question. As you can see in the image, it is shown with Red Text as opposed to just being regular typed text!) 

 

All this code does is Hide the panel whenever the value of WorkflowState matches the value "State 1", "State 2", or "State 3" as indicated by the case statements. If it doesn't, then it will default to false, and the Panel will be Shown. 

 

Because you can add new handled cases relatively easily, in the event that I were to add a new Choice for my Column, I by adding a new case to the Rule, it can be accounted for without too much work. 

 

The JavaScript

 

The time has come for the JavaScript! 

How you add this to your form is entirely up to you. You can either drop it into the Custom Javascript portion of the Settings, or you can save it to a file and reference it in the Advanced -> Custom JavaScript Includes URL referencer. Either way, this includes most (but not all) of the Repeating Section Boilerplate that I use to handle all things Repeating Sections for my form in a common Namespace (NCU). 

 

There are plans to eventually release all of the Javascript functions and tools that I have built under this common library name, but I still have a lot of testing to do. Most of everything that is being done in the code is heavily commented so that you should be able to read what it does, but if you need additional explanations, feel free to ask. 

/* global NWF$, NWF, NF, outerDiv, ValidatorOnLoad, _spPageContextInfo */
/* eslint-env browser */
/* eslint no-console: ["error", { allow: ["log", "error"] }]  */

/*global 
  NWF$, NWF, NF, outerDiv, ValidatorOnLoad, _spPageContextInfo 
*/

/* Tabbed Form code */


/* 
  We're going to create a convenient Namespace to store all of our
  Form Variables and Functions in, so that we can keep those out of the 
  Global Scope 
*/

var NCU = (function (NCU) {
  "use strict"; 

  NCU.FormVariables = (function (obj) {  
    obj.hiddenRepeaterPanelClasses = ["ReceiptPanel"];
    obj.pageIsReady = false;
    return obj;
  }(NCU.FormVariables || {}));

  /* 
    Now we'll set up our FormFunctions property which will contain
    all of our custom Functions.
  */
  NCU.FormFunctions = (function (obj) {

    /*
      This fixes the incorrect way that Nintex Forms increase / decrease the
      height of the Form Canvas. By leaving in the FormFiller Events below, 
      all instances where the height would have a chance to grow out of control
      in either direction, should be fixed 
    */
    obj.setCanvasContainerHeight = function () {
      if (outerDiv.data("outerDivHeight") !== outerDiv.height()) {
        outerDiv.outerHeight(outerDiv.height());
        outerDiv.data("outerDivHeight", outerDiv.height());
      }
    };

    obj.rebuildHiddenRepeaterSections = function (eventRow) {
      var thisRepeatingSection = eventRow.closest("[data-controlname]");
      var thisFormControlID = thisRepeatingSection.attr("formcontrolID");
      var formFillerDivCurrent = NWF.FormFiller.Functions.GetFormFillerDiv();
      var siblingRepeatingSection = formFillerDivCurrent.find(".nf-repeater:hidden").closest("[data-controlname]").not("[formcontrolid='" + thisFormControlID + "']");
      siblingRepeatingSection.each(function (index, section) {

        var thisSiblingSection = NWF$(section);
        var thisRepeaterControl = thisSiblingSection.find(".nf-repeater");
        var thisRepeaterInnerControl = thisRepeaterControl.parent();
        var thisSiblingSectionRows = thisSiblingSection.find(".nf-repeater-row:not(.nf-repeater-row-hidden)");

        var totalRowHeight = 0;
        thisSiblingSectionRows.each(function (index, row) {
          totalRowHeight += NWF$(row).outerHeight();
        });

        if (totalRowHeight > thisRepeaterControl.height()) {
          thisRepeaterControl.height(totalRowHeight);
        }

        thisRepeaterInnerControl.height(thisRepeaterControl.height());

        if (thisSiblingSection[0].className.indexOf('nf-error-highlight') != -1) {
          thisSiblingSection.outerHeight(thisRepeaterControl.outerHeight() + 4);
        } else {
          thisSiblingSection.outerHeight(thisRepeaterControl.outerHeight());
        }
      });
    };
    
    obj.RepositionAndResizeOtherControlsAndFillerContainerHeight = (NWF.FormFiller.Functions.RepositionAndResizeOtherControlsAndFillerContainerHeight || NWF.FormFiller.Resize.RepositionAndResizeOtherControlsAndFillerContainerHeight);
    
    obj.hideRepeatingSectionPanels = function (panelClassArray) {

      if (NWF$.isArray(panelClassArray)) {

        NWF$.each(panelClassArray, function (index, panelClass) {

          if (panelClass) {

            if (panelClass.match(/^\./) === null) {
              panelClass = "." + panelClass;
            }

            NWF$(panelClass + ".nf-filler-control").each(function (index, targetPanel) {
              /* Get the current Panel that we're iterating over */
              targetPanel = NWF$(targetPanel);

              /*  Get the current Row that the Panel is in */
              var currentRow = targetPanel.closest(".nf-repeater-row");

              /*  If the Panel is NOT visible (because it was hidden by a RULE) */
              if (!(targetPanel.is(":visible"))) {

                /*  Get the Outermost Height of the Panel */
                var panelHeight = targetPanel.outerHeight();

                /*  If the CURRENT ROW is not the HIDDEN ROOT ROW, then we need resize our Canvas / Form */
                /*  Because the Panel was actually taking up space there! */
                if (!currentRow.hasClass("nf-repeater-row-hidden")) {
                  obj.RepositionAndResizeOtherControlsAndFillerContainerHeight(currentRow, -panelHeight, -panelHeight, NWF$("#formFillerDiv"));
                }

                /* Then we take the Height out of the Row itself (because RS Rows do not auto resize) */
                currentRow.outerHeight(currentRow.outerHeight() - panelHeight);
              }
            });
          }
        });
      }
    };

    return obj;
  }(NCU.FormFunctions || {}));

  /* Added Prototypes */
  String.prototype.format = function () {
    var s = String(this);
    var i = arguments.length;

    while (i--) {
      s = s.replace(new RegExp("\\{" + i + "\\}", "gm"), arguments[i]);
    }
    return s;
  };


  
  /* 
    Validator Rules can sometimes become orphaned when a New Row is added.
    If the function exists which can reattach them to their associated Controls, 
    this will make sure that it runs every time so that every row can be validated in real time. 
  */  
  if (typeof ValidatorOnLoad !== "undefined") {
    NWF.FormFiller.Events.RegisterRepeaterRowAdded(function () {
      ValidatorOnLoad();   
    });
  }
  
  /*
    The below FormFiller.Events are in place to handle how the Form will
    incorrectly set the Form Height as Controls are Hidden and Shown
    via the Rule System and other interactions.
  */
  NWF.FormFiller.Events.RegisterRepeaterRowAdded(function (thisRow) {
    NCU.FormFunctions.rebuildHiddenRepeaterSections(thisRow);
    NCU.FormFunctions.setCanvasContainerHeight();
  });

  NWF.FormFiller.Events.RegisterRepeaterRowDeleted(function (thisRow) {
    NCU.FormFunctions.rebuildHiddenRepeaterSections(thisRow);
    NCU.FormFunctions.setCanvasContainerHeight();
  });  

  NWF.FormFiller.Events.RegisterControlShowHidePropagated(function () {
    if (arguments[0].data("RepositionControls")) {
      NCU.FormFunctions.setCanvasContainerHeight();
    }
  });

  NWF.FormFiller.Events.RegisterControlHeightChangePropagated(function () {
    NCU.FormFunctions.setCanvasContainerHeight();
  });
  
  NWF.FormFiller.Events.RegisterBeforeReady(function () {
    if (NF.BaseDataAccessHelper === undefined) {
      try {
        console.log("Attempting to load missing js file: 'NF.BaseDataAccessHelper.js'");
        NWF$.getScript(_spPageContextInfo.siteAbsoluteUrl.replace(/sites.+/, "") + _spPageContextInfo.layoutsUrl + "/NintexForms/JavaScriptStringHandler.ashx?" + "resourceType=jsfile&" + "fileName=NF.BaseDataAccessHelper.js&" + "culture=" + _spPageContextInfo.currentCultureName);
      } catch (e) {
        console.log("There was a problem grabbing the BaseDataAccessHelper using the JavaScriptStringHandler!");
        console.log(e);
      }
    }

    outerDiv.outerHeight(outerDiv.height());
  });
  
  /*  
    When the Form loads, but before it's visible, we need make sure that the Repeating Section
    is correctly sized. Specifically, we need to make sure that the Panel where information *might*
    reside on a Task form but not on an Edit Form, has been hidden and that its height has been
    subtracted from the rows it is contained in, as well as the canvas.
    The following For Each loop will do just that...
  */  
  NWF.FormFiller.Events.RegisterBeforeFillerVisible(function() {
    NCU.FormFunctions.hideRepeatingSectionPanels(NCU.FormVariables.hiddenRepeaterPanelClasses);  
  });

  NWF.FormFiller.Events.RegisterAfterReady(function () {
    outerDiv.data("outerDivHeight", outerDiv.height());
    NCU.FormVariables.pageIsReady = true;
  });

  return NCU;
}(NCU || {}));

The ONLY thing you should need to change will be at the top of the function in the FormVariables section where you'll see the following bit of code: 

NCU.FormVariables = (function (obj) {  
    obj.hiddenRepeaterPanelClasses = ["ReceiptPanel"];
    obj.pageIsReady = false;
    return obj;
  }(NCU.FormVariables || {}));

Notice how the value of obj.hiddenRepeaterPanelClasses is an Array containing a string with the Value of "ReceiptPanel", the same as the CSS Class we gave to our Panel? If you change the CSS Class name of that panel you will absolutely need to change the code to mirror whatever name  you decide to give the class!!!!

Failure to do so will result in your Repeating Section no longer resizing correctly! 


The Results

 

Now that you have put everything in its place, we can test to see if it works. 

Creating a new Item with a WorkflowState of "State 1" will present the form to us as shown: 

image.png

(Note: I have added a few rows so that you can see it's working

 

If we were to change the value of WorkflowState to something like "State 4", "State 5", or "State 6", the form will present to us as: 

image.png

 

The Catch

 

There are a few limitations to what I have presented here. One of the biggest being, if you were to put the Form into a state where the second panel was Shown, but you added a new Row, it would still mess up the Resizing. 

While I have some ideas on how to solve that, I am currently too busy to immediately produce anything useful, so it would likely take a little time if it is indeed something you all do. 

 

If it isn't, then you may want to make sure that you're disabling the ability to Add / Delete new Rows once you reach certain states. 

I hope that this helps to put you on the path of solving your problem. 

 

Reply
kelliganp
Nintex Newbie

Re: Resize a Repeating Section After Hiding Panels inside the Section

Jump to solution

Hi @MegaJerk,

 

It worked and was a very simple set of instructions for me to follow! I did have a bit of an issue with our footer (corporate branding package) overlaying the first panel on my first test but corrected when I manually changed the state. I will need to do a more testing and possibly deactivate the branding package on this site. Not a big deal.

 

I will spensd some time looking over the code to see if I have any questions on the other things you included in your code.

YOU ROCK!

 

Thanks and Best Regards,

Patrick

0 Kudos
Reply
kelliganp
Nintex Newbie

Re: Resize a Repeating Section After Hiding Panels inside the Section

Jump to solution

Hello again @MegaJerk,

 

My colleague, @gbone02, and I are implementing this solution and we ran across a bit of a glitch. First of all, we have a branding package that the company has deployed across the platform and the footer is somtimes rendering over-top of the form content on the tab that conrtains the repeating section we are controling. There is also a panel at the bottom of the form template that has no rules assigned to it, so it should show up on all tabs at the bottom. It too, is rendering overlaid on the repeating sevion. I have posted a screenshot of the issue. Do you have any thoughts or ideas on how to force the content to render in order?

20190911 Screenshot 0001.png

 

Thanks and Regards,

Patrick

0 Kudos
Reply
MegaJerk
Nintex Newbie

Re: Resize a Repeating Section After Hiding Panels inside the Section

Jump to solution

I'd have to take a more in-depth look at your form to be of any help at this point.

 

Without an export, my guess is that when you change tabs, there is a brief moment (before my code kicks in) where the Section is calculated in an erroneous way (probably at 0 height because of the aforementioned errors in how Nintex Form calculates RS Height on Hide). Because of this, the height of everything is made smaller than it should be, and the Footer repositions in a way that is minus the Height of the Repeating Section. Immediately afterwards though, my code kicks in and corrects the Height of the Repeating Section and subsequent sibling items. I do not know however if that would cascade out to all of the siblings beyond the Panel the RS is contained inside of (IE: Any Control outside of the Panel). 

One way to approach a solution to this problem might be to just throw the Footer into its own panel (if it isn't already) and set some hard positioning logic on it any time a Tab has been changed and the Tab Panel has had its Height adjusted. This way when the Tab Panel is adjusted appropriately, you can just say something along the lines of: 

NWF$([data-controlnam='FooterPanel']).css({top: TabPanel.position.top + TabPanel.outerHeight() + 4}); 

This is just a Rough Example, but it's mostly what I think will work. 

0 Kudos
Reply
Highlighted
kelliganp
Nintex Newbie

Re: Resize a Repeating Section After Hiding Panels inside the Section

Jump to solution

Hi @MegaJerk! Thanks for responding.

 

Is there a way I can send you the list template? I do not want to post it here publicly as there are possibly too many company URL references built in.

 

The footer is part of a farm-deployed branding package that I have no control over so it renders independent of my form layout I think. I can turn off the branding package on my site collection from the Solutions Gallery but I would like to avoid that if I can. The issue still happens for the other panel I mentioned so I will see if I can get your code sample to work with the "Current State" control from the screen shot.

 

Thanks and Regards,

Patrick

0 Kudos
Reply