Monday, August 12, 2013

Walkthrough: Conditionally Hide Fields on SharePoint 2010 Standard List Forms using jQuery

Introduction

To conditionally hide fields on a SharePoint 2010 list form (new, edit, and display), use jQuery.  Using jQuery, you can control the visibility of fields and even rows of fields with just a few lines of code.  What's more, you will be able to do this using nothing more than SharePoint 2010 Standard, which doesn't come with InfoPath Forms Services.

In this walkthrough, I will show you how to show and hide a couple of form elements based upon what option the user selected from a dropdown element.  We'll start first with the New list item form, and then work through the Edit and Display list item forms. These walkthroughs will assume that you already are conversant with SharePoint 2010 and know how to use SharePoint Designer 2010 to create new list forms, bind form elements to data sources, edit markup and so on.  It also assumes that you know how to create custom lists and configure their fields.  These walkthroughs are based upon jQuery 1.9.1.  Here are the key elements to be used in these walkthroughs:
  • Lists
    • List1 (data list)
      • Field1 (choice: Yes, No)
      • Field2 (linked: List2)
      • Field3 (multi-line text)
    • List2 (lookup)
      • Field {Option1, Option2, Option3, Option4}
  • Form Field Elements
    • Dropdown1 (SharePoint Dropdown)
      • Yes
      • No
    • Dropdown2 (SharePoint Dropdown)
      • Option1
      • Option2
      • Option3
      • Option4
    • Multiline1 (SharePoint Multiline)
List1 is the data list, to which the New, Edit and Display forms attach.  Field1 in this list is configured as a choice field with just two options: Yes and No.  The default option is left BLANK.  Field2 is linked to the lookup list, List2; and Field3 is a simple multiline text area.  List2 is a lookup list having a single field and which is populated with the options you want to display in the Dropdown2 form field.

In the first walkthrough, we will code the New list form to display fields Field2 and Field3 only if the user has selected Yes from Field1.  The second walkthrough, involving the Edit list form, is essentially the same as the first one.  The third walkthrough, involving the Display list form will require some modifications to the code in order to walk the DOM a little farther to find the elements and to clean up the text.

Walkthrough I: Conditionally hide fields on the SharePoint 2010 New list item form

In SharePoint Designer 2010, create a new custom New list form.  On this form, drop in the three SharePoint field elements noted above, or have them autogenerated, and bind them appropriately to the data source (List1).  In Code view, add a reference to the jQuery file.  Set your new custom New form as the default new form for the list.  The resultant form should have a simple vertical table layout with two columns: one for labels and one for input elements.

Test the list by trying to add a new row to the list.  Make sure that it properly writes inputted data to List1. With the New form displayed in a browser, view the source.  Look through the markup until you find your fields (search under Field1, Field2...).  When you find them, take note of the following for each field:
  • Title
  • ID
  • Name
Also, identify these same attributes for the LABEL element associated with each of these fields.  Note that the TITLE attribute of fields Field1 and Field2 is the same as the name you gave these fields when you created List1.  Note also that the multiline element does not have a TITLE attribute but it does have an ID attribute.  You'll need to note these bits of information because you will be finding them (through jQuery) in the DOM through these unique attributes. Here's the code:
$(document).ready(function(){   //When the New list form is first displayed or refreshed, hide the form elements   //or display them appropriately on refresh...   //To do this, get the value of the choice that the user selected...   var selected = $("select[title = 'Field1']").val();   if(selected == "yes") {     //...show the rows containing the labels and fields. Do this by first searching     //the DOM for the element with title 'Field2', and then moving back up     //the DOM to the first table row element and show it...     $("select[title = 'Field2']").closest("tr").show();     //and then repeat this process for the field with ID 'ID-Of-Field3'.  Note that     //this value will be a very long string and will not appear in Designer...     $("ID-Of-Field3").closest("tr").show();   }   else {     //...hide the rows.     $("select[title = 'Field2']").closest("tr").hide();     $("ID-Of-Field3").closest("tr").hide();     //and also reset their values...     $("select[title = 'Field2']").get(0).selectedIndex = 0;     $("ID-Of-Field3").val("");   };   //Next, bind a new function to the CHANGE event of the dropdown, Field1,   //in order to capture user choices and hide/show the rows appropriately...   $("select[title = 'Field1']").bind("change", function(){     //Start this function by getting the value of the choice that the user selected...     var selected = $("selected[title = 'Field1']").val();     //Now do something based upon that choice...     if (selected == "Yes"){       //...show the row containing the fields.  To do this, first search       //the DOM for the element with this title and then move back up       //the DOM to the first table row element and show it...       $("select[title = 'Field2']").closest("tr").show();       //Then search the DOM for the first element with this ID and move       //back up the DOM to the first table row element and show it...       $("ID-Of-Field3").closest("tr").show();     }     else{       //...hide the fields.  To do this, repeat the code above, but set       //the elements to Hide instead of Show...       $("select[title = 'Field2']").closest("tr").hide();       $("ID-Of-Field3").closest("tr").hide();       //and, while we're at it, let's also reset any value they might contain...       $("select[title = 'Field2']").get(0).selectedIndex = 0;       $("ID-Of-Field3").val("");     }   }); });
This code has been tested in both IE8 and FF17 without issue and will work so long as you do not change the form elements you originally had on the New form.  When the user selects YES, the two rows containing the elements of interest will be shown.  If the user selects NO, these rows and their elements will be hidden.

Walkthrough II: Conditionally hide fields on SharePoint 2010 Edit list form

The code for the list Edit form is the same as for the list New form.  Just copy and paste.

Walkthrough III: Conditionally hide fields on SharePoint 2010 Display list form

This walkthrough will use the existing autogenerated list display form.  The display form doesn't have the usual form fields in it. In fact, it doesn't use the usual form fields at all.  No matter.  You can use jQuery to move through the DOM, find the appropriate HTML elements, and then base your condition statement on what you find there. 

SharePoint 2010 list display forms identify displayed text via bookmarks, which will be uniquely identified in the page.  Using these bookmarks, you can find the appropriate element using jQuery.  Now, we only want to hide the other fields if the user has previously selected No from Field1.  Here's the code:
$(document).ready(function(){   //First, find the anchor tag having the name, Field1.  Then move up the DOM to the nearest   //header tag, and then move up from there to the nearest table cell tag.  Having found the   //cell containing the Yes or No selection, move down the DOM to the element that actually   //contains the Yes/No string and get it...   var field = $("A[name = 'SPBookmark_Field1']").closest("h3").closest("td").next().text();   //Having got this string, it needs to be cleaned up of the comment tags SharePoint 2010 uses   //to identify this field...   //First, replace all spaces in the string...   field = field.replace(/ /g, '');   //then replace all line breaks and other such characters...   field = field.replace(/ (\r\n|\n|\r)/gm, '');   //lastly replace any tabs...   field = field.replace(/(\t)/gm,'');   //Having extracted the Yes or No user selection, operate on it...   if(field == "No"){     $("A[name = 'SPBookmark_Field2']").closest("tr").hide();     $("A[name = 'SPBookmark_Field3']").closest("tr").hide();   }; });
Summary

Using jQuery makes coding conditional fields on your SharePoint 2010 forms a snap, and it's amazing how few lines you need to write.  Of course, that's because the good folks at the jQuery foundation have developed an awful lot of code to do all of the heavy lifting for you.  What you've done here is just the start to making your simple SharePoint 2010 forms much more dynamic out of the box without having to upgrade to SharePoint 2010 Enterprise and InfoPath Services.

Tips
  • You cannot make SharePoint 2010 checkboxes required.  If you want to require that a user selects a Yes/No type element, use a dropdown with {Yes, No} options instead.
  • Make sure there is no space between "select" and "[". Otherwise the selector will fail.
  • Study the source of your list display forms against the jQuery code here to see how it walks the DOM to find the appropriate elements.
References

4 comments:

Anonymous said...

Thanks for the Scripts, very useful
I would like to note though that the display form didn't work for me until I added this line which is meant to remove white spaces:
field = field.replace(/\s/g,'');

Paulo said...

Hello.

In what part of the newform do you put the code above?

Thank you!


Paulo

Al said...

Paulo - there are many ways to do this. Here's been my approach: 1) I upload the jQuery library file itself to a document library; 2) modify the MasterPage to include the appropriate reference to this file by inserting it into the "PlaceHolderAdditionalPageHead" asp content region; 3) then add a content editor web part to the page, configure it to be hidden, and add the script to this web part.

Al said...

Also, here's an outstanding reference that walks you through the different methods for implementing custom script into SharePoint pages: Adding jQuery to SharePoint