Custom Validations in SharePoint Form Using JQuery: Part 1

There are times when we need to perform custom validations in a SharePoint (New/Edit) list form. This can be done using jQuery. In this article and the next, I will explain a scenario involving such validations and some gotchas.

Let us assume our requirement has a list called "Activity Tracker" to capture various activities that a team of members have worked on for a week. The list has the following fields:

  1. Activity Description (Text field)
  2. Category (Drop down with the values Sales, Competency and Coding)
  3. Update for the week (Text area)
  4. Team members involved (Drop down)
  5. Status (Drop down with the values In Progress, Completed and Closed)
  6. Completion Date (Date and Time)
  7. Revenue (Text field)
  8. Competency (Text area)
Let us understand the following validation requirements from the table below.

Column Name Field Type New Form Edit Form
Activity Description Text field Mandatory Non-editable
Category Drop down Mandatory Non-editable
Update for the week Text area Not-Mandatory editable
Team members involved Drop down Mandatory editable
Status Drop down Visible only if Category is Sales or Coding
Mandatory only if Category is Sales or Coding
Editable, Visible only if Category is Sales or Coding
Completion Date Date Time Visible only if Category is Sales or Coding
Mandatory only if Category is Sales or Coding
Editable, Visible only if Category is Sales or Coding
Revenue Text field Visible only if Category is Sales or Coding
Mandatory only if Category is Sales or Coding
Editable, Visible only if Category is Sales or Coding
Competency Details Text field Visible only if Category is Competency
Mandatory only if Category is Competency
Editable, Visible only if Category is Competency

To interpret the table, let's use an example.

Status is a choice field, that needs to be visible only if the user chooses "Sales" or "Coding" in the "Category" field. In such cases, apart from being visible, it also needs to be mandatory. In edit mode, this field needs to be editable.

Similarly, we can interpret the remaining column validations.

Now let us proceed to the solution. Here are the list columns for reference.

list columns

When we create the list, please mind that the following columns should not be mandatory by definition:

  • Those columns that are non-mandatory in general
  • Those columns that are to be hidden under some condition

Even if they are mandatory in other conditions then if they need to be invisible / non-mandatory in even a single condition, they should be made non-mandatory in the list definition. We need to do the required field validation (and display indication) by other means, we will get to it in a minute. The reason being, if the column is made mandatory and we hide it using jQuery (in the scenario that it needs to be hidden), then the form will fail to save and the error will be displayed that the column needs to be filled in, even though the column should not be visible in that case.

Therefore in our case, Update for the week, Status, Completion Date, Revenue and Competency are all marked as non-mandatory by list definition.

Next, we need to edit the list forms to implement these validations.

In the new form, after:

<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">

Add references to the jQuery libraries and a custom JavaScript file that we create as follows:

    <script language="javascript" type="text/javascript" src="../../jQuery Scripts/jquery.min.js"></script>

    <script language="javascript" type="text/javascript" src="../../jQuery Scripts/Tracker.js"></script>

    <script language="javascript" type="text/javascript">

        $(document).ready(function () {

            OnTypeNotificationChangeNewForm();

            var vItem = $("select[title=Category]");

            $(vItem).change(function () {

                OnTypeNotificationChangeNewForm();

            });

        });

        function PreSaveAction()

        { return ValidateNewForm(); }

    </script>
 
Here, notice that we are calling the method OnTypeNotificationChangeNewForm() on the ready function and whenever the Category dropdown is selected, as indicated by the following lines:
 

var vItem = $("select[title=Category]");

$(vItem).change(function () { OnTypeNotificationChangeNewForm(); });


This function is defined in the Tracker.js file, that is referenced above. Now let us look at this function in the Tracker.js file.

function OnTypeNotificationChangeNewForm()

{     

     if(( $("select[title='Category'] option:selected").text() == "Sales")||( $("select[title='Category'] option:selected").text() == "Coding"))

     {

          HideColumn("Competency Details","True");                   

          HideColumn("Activity Description","False");

          HideColumn("Update for the week","False");

          HideColumn("Team members involved","False");

          HideColumn("Status","False");

          HideColumn("Completion Date","False");

          HideColumn("Revenue","False");                        

          MandateColumn("Competency Details","False");

          MandateColumn("Update for the week","False");                    

          MandateColumn("Activity Description","True");

          MandateColumn("Team members involved","True");

          MandateColumn("Status","True");

          MandateColumn("Completion Date","True");

          MandateColumn("Revenue","True");

     }

     if( $("select[title='Category'] option:selected").text() == "Competency")

     {

         HideColumn("Competency Details","False");                  

         HideColumn("Activity Description","False");

         HideColumn("Update for the week","False");

         HideColumn("Team members involved","False");

         HideColumn("Status","True");

         HideColumn("Completion Date","True");

         HideColumn("Revenue","True");                  

         MandateColumn("Competency Details","True");

         MandateColumn("Update for the week","False");                    

         MandateColumn("Activity Description","True");

         MandateColumn("Team members involved","True");

         MandateColumn("Status","False");

         MandateColumn("Completion Date","False");

         MandateColumn("Revenue","False");

   }

}
 
Here, we are checking the value in the dropdown titled "Category" and based on that we are calling the "HideColumn" and  "MandateColumn" methods, passing the column name and a Boolean value, indicating the corresponding function to show, hide, mandate or non-mandate that specific column.
 
Now let us look at the "HideColumn" method.

The following is the definition of "HideColumn".
 

function HideColumn(Column,IsHide )

{

     if(IsHide=="True")

     {  

        $('nobr:contains("'+Column+'")').closest('tr').hide();

     }

     else

     { 

        $('nobr:contains("'+Column+'")').closest('tr').show();

     }

}


Here, if the second parameter is true (in other words, hidden) then we are finding the entry in the source with the <nobr> tag  that encloses the Column name passed in the first parameter and hiding the nearest <tr> to this <nobr>. If the second parameter is false (in other words, not hidden) then we are showing the <tr>. This relies on the mechanism where SharePoint list forms have the list fields in rows and the <nobr> tags in an orderly fashion.

Now let us look at the "MandateColumn" method.

The following is the definition of "MandateColumn".
 

function MandateColumn(ColName, mandatory)

{

    if(mandatory=="True")

    {

          var spanTag ="<span class=\"ms-formvalidation\"> *</span>";

            var newHtml = ColName;

            if (mandatory)

            {

                newHtml += spanTag;               

                $("nobr").filter(function() {

                return $(this).text() === ColName;

                }).html(newHtml);

            }

      }

      else

      {    

      }

}

Here, if the second parameter is true (in other words, mandate), we are finding the entry in the source with the <nobr> tag that encloses the Column name passed in the first parameter, and adding a <span class=\"ms-formvalidation\"> *</span>" tag to this <nobr> HTML. If the second parameter is false (in other words, not mandate) then we are doing nothing. This is to display a red star next to the column name in the new form as it happens when the validation is triggered by the list column definition. Basically, even though the columns are not specified as "Required" by the list definition, we are trying to emulate the display that it is compulsory for the end user to fill in a value in this column.

Next is the "ValidateNewForm()" method, that does the actual validation.
 

function ValidateNewForm()

{

      var missingFields="";

 

      if($("input[title='Activity Description']").val().length <1)

      {

            missingFields+="Activity Description ,";        missingFields+="\n";

      }    

      if ($("select[title='Category']").val()==0)

      {

      missingFields+="Category ,";        missingFields+="\n";

      }

      if($("textarea[title='Update for the week']").val().length <1)

      {

            missingFields+="Update for the week ,";         missingFields+="\n";

      }

      if ($("select[title='Team members involved']").val()==0)

      {

      missingFields+="Team members involved ,";       missingFields+="\n";

      }

      if ($("select[title='Status']").val()==0)

      {

      missingFields+="Status ,";          missingFields+="\n";

      }

      if($("input[title='Completion Date']").val().length <1)

      {

            missingFields+="Completion Date ,";       missingFields+="\n";

      }

      if($("input[title='Revenue']").val().length <1)

      {

            missingFields+="Revenue ,";         missingFields+="\n";

      }

      if($("textarea[title='Competency Details']").val().length <1)

      {

            missingFields+="Competency Details ,";          missingFields+="\n";

      }

     

      if(( $("select[title='Category'] option:selected").text() == "Sales") ||( $("select[title='Category'] option:selected").text() == "Coding"))

      {

      missingFields=missingFields.replace("Update for the week ,\n","");

      missingFields=missingFields.replace("Competency Details ,\n","");

      }

      else if( $("select[title='Category'] option:selected").text() == "Competency")     

      {

      missingFields=missingFields.replace("Update for the week ,\n","");

      missingFields=missingFields.replace("Status ,\n","");

      missingFields=missingFields.replace("Completion Date ,\n","");

      missingFields=missingFields.replace("Revenue ,\n","");

      }

 

      var isFormValid=(missingFields.length==0);

     

      if(!isFormValid)

      {

                  alert("     Please enter values in the following fields - " +"\n"+ missingFields);  

      }    

     

      return isFormValid;

}
 
Let us understand this method.

Here, we are creating a string "missingFields" and adding to this string, whenever the controls in the form are found empty (in the case of a text box, we are checking if "val().length<1"; in case of dropdown control, we are checking if ".val()==0" ).
 

var missingFields="";

if($("input[title='Activity Description']").val().length <1)

{

   missingFields+="Activity Description ,";        missingFields+="\n";

}    

if ($("select[title='Category']").val()==0)

{

    missingFields+="Category ,";        missingFields+="\n";

}

Finally, we are checking the condition. If the category is Sales or Coding then we are removing the error message pertaining to the "Update for week" column (that is anyways non-mandatory) and "Competency Details" ( that is not visible and mandatory for the sales and the coding category).

Similarly, we are checking the condition. If the category is Competency then we are removing the error message pertaining to the "Update for week" column (that is anyways non-mandatory) , "Status", Completion Date" and  "Revenue" (that are not visible and mandatory for the Competency category)
 

if(( $("select[title='Category'] option:selected").text() == "Sales") ||( $("select[title='Category'] option:selected").text() == "Coding"))

{

      missingFields=missingFields.replace("Update for the week ,\n","");

      missingFields=missingFields.replace("Competency Details ,\n","");

}

else if( $("select[title='Category'] option:selected").text() == "Competency")     

{

      missingFields=missingFields.replace("Update for the week ,\n","");

      missingFields=missingFields.replace("Status ,\n","");

      missingFields=missingFields.replace("Completion Date ,\n","");

      missingFields=missingFields.replace("Revenue ,\n","");

 }


If there are any error messages left in the string then we are displaying the message and preventing the form from being saved.

If we save the tracker.js and NewForm.aspx, hopefully, the validations should fire in the NewForm mode. When Sales or Coding is selected, observe that some columns are displayed as mandatory.

NewForm mode

When Competency is selected, observe that some columns (status, revenue and completion date) are not displayed and the Competency column is being displayed as mandatory.

EditForm mode

The Edit form is a tad bit different. We will see that in the next article.

Next Article  Custom Validations in SharePoint form using jQuery: Part 2