In the previous article Custom Validations in SharePoint form using jQuery: Part 1, we saw how to implement custom validations in a SharePoint list NewForm using jQuery.
In this article, we shall look at the editform scenario. Let us do a quick recap of the 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 |
Specifically, let us understand an example edit scenario.
Status is a choice field, that needs to be visible in edit mode only if the entry has "Sales" or "Coding" in the "Category" field. In such cases, the Status must visible, mandatory and must display the previous entry in the column made using NewForm.
Similarly, we can interpret the remaining column validations.
Now let us proceed to the solution. Here are the list columns for reference.
When we create the list, please be aware 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, 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 that in a minute. The reason being, if the column is made mandatory and we hide it using jQuery (when it does need 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.
As seen in the previous article, Update for the week, Status, Completion Date, Revenue and Competency are all marked as non-mandatory by list definition.
Next, we need to modify the edit form to implement these validations.
In the Edit Form:
After the <asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server"> ,
Add references to jQuery libraries and a custom JavaScript file as in the following:
<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 () {
OnTypeNotificationChangeEditForm();
});
function PreSaveAction() {
SetValuesInDisabledColumns();
return ValidateEditForm();
}
</script>
Here, notice that we are calling a method, OnTypeNotificationChangeEditForm() on the ready function. Also notice the function SetValuesInDisabledColumns() in PreSaveAction. This is an important function, we get to it in a minute.
This function OnTypeNotificationChangeEditForm () is defined in the Tracker.js file, that is referenced above. Now let us look at this function in the Tracker.js file.
function OnTypeNotificationChangeEditForm() {
if (($("select[title='Category'] option:selected").text() == "Sales") || ($("select[title='Category'] option:selected").text() == "Coding")) {
DisableColumn("Title", "True");
DisableColumn("Activity Description", "True");
DisableColumn("Category", "True");
DisableColumn("Update for the week", "False");
DisableColumn("Team members involved", "False");
DisableColumn("Status", "False");
DisableColumn("Completion Date", "False");
DisableColumn("Revenue", "False");
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") {
DisableColumn("Title", "True");
DisableColumn("Activity Description", "True");
DisableColumn("Category", "True");
DisableColumn("Update for the week", "False");
DisableColumn("Team members involved", "False");
DisableColumn("Competency Details", "False");
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", "True");
MandateColumn("Revenue", "False");
}
}
Here, we are checking the value in the dropdown titled "Category" and based on that we are calling the "DisableColumn", "HideColumn" and "MandateColumn" methods, passing the column name and a Boolean value, indicating the corresponding function to enable, disable, show, hide, mandate or non-mandate that specific column.
Now, let us look at the "DisableColumn" method.
The following is the definition of "DisableColumn".
function DisableColumn(Column, IsDisable) {
if (IsDisable == "True") {
$('nobr:contains("' + Column + '")').closest('tr').attr('disabled', true);
$("input[title='" + Column + "']").attr('disabled', true);
}
else {
$('nobr:contains("' + Column + '")').closest('tr').prop("disabled", false);
$("input[title='" + Column + "']").prop("disabled", false);
}
}
Here, if the second parameter is true (in other words, Disable), we are finding the entry in the source with a <nobr> tag that encloses the Column name passed in the first parameter and making the "disabled" attribute the nearest <tr> to this <nobr> as "true". We are also finding the control with the title set to the ColumnName and setting its 'disabled' attribute to "true".
$('nobr:contains("'+Column+'")').closest('tr').attr('disabled',true); $("input[title='"+Column+"']").attr('disabled',true);
If the second parameter is false (in other words, not disabled) then we are finding the entry in the source with the <nobr> tag that encloses the Column name passed in the first parameter, and making the "disabled" attribute the nearest <tr> to this <nobr> as "false". We are also finding the control with the title set to the ColumnName and setting its 'disabled' attribute to "false".
$('nobr:contains("'+Column+'")').closest('tr').prop("disabled", false); $("input[title='"+Column+"']").prop("disabled",false);
As seen in the previous article as well, this relies on the mechanism where SharePoint list forms have the list fields in rows and <nobr> tags in an orderly fashion.
The "HideColumn" and "MandateColumn" methods have the same definition in the previous article Custom Validations in SharePoint form using jQuery: Part 1. We can reuse the methods used for NewForm.aspx.
Next comes the "SetValuesInDisabledColumns()" method. In SharePoint, when an input control has the "disabled" attribute set to "true", when the form is submitted, the values in the control are not submitted. This gives rise to issues that the value is lost (either overrides the existing value if the column is non-mandatory or the form submission fails if the column is a mandatory column). For this purpose, before submitting for validation, we need to set back the "disabled" property for all controls in the form (irrespective of whether they are mandatory or not) to "false", so that form validation and submission proceeds without any issue. This is exactly what the method SetValuesInDisabledColumns () does.
Here is the code for this method:
function SetValuesInDisabledColumns() {
DisableColumn("Title", "False");
DisableColumn("Activity Description", "False");
DisableColumn("Category", "False");
DisableColumn("Update for the week", "False");
DisableColumn("Team members involved", "False");
DisableColumn("Status", "False");
DisableColumn("Completion Date", "False");
DisableColumn("Revenue", "False");
DisableColumn("Competency Details", "False");
}
That is, in this function, we are calling the DisableColumn for all the fields in the form with a "False" parameter, indicating that all fields are enabled.
Next comes the "ValidateEditForm()" method, that does the actual validation.
function ValidateEditForm() {
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 ($("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;
}
This method is similar to the one in NewForm.
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 the case of a 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 / 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 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 EditForm.aspx then hopefully, the validations should fire in EditForm mode. When we check editing a list entry with Sales / Coding in the Category, observe that:
- Title, Activity Description and Category are disabled for edit
- Title, Activity Description, Category, Team members involved, Status, Completion Date and Revenue are marked mandatory
- The Competency Details column is not visible
- All the values entered using the NewForm are visible in all the fields
When we check editing a list entry with Competency in Category, observe that
- Title, Activity Description and Category are disabled for edit
- Title, Activity Description, Category , Team members involved and Competency Details are marked mandatory
- Status , Completion Date and Revenue Columns are not visible
- All the values entered using the NewForm are visible in all the fields
Hope the series is helpful to those who are looking to implement custom validation in SharePoint list forms using jQuery.
Previous Article: Custom Validations in SharePoint Form using jQuery: Part 1