Validation on SharePoint Forms – Part Two

In my previous post I outlined a few approaches to validation in SharePoint forms.  In this post, I’ll give some simple examples of how you might validate some date inputs.  For this example, I’m using a little Paid Time Off (PTO) application I built for one of my clients.  The basic idea was that the employees could make a request for time off, and the request could be approved or denied by their manager (using SharePoint Designer-based workflow).  There was some reporting around all of this as well.

I built a  List called Requests for PTO, and of course got the default forms (NewForm.aspx and EditForm.aspx).  On both forms, I converted the List Form Web Parts (LFWPs) to Data View Web Parts (DVWPs) so that I could better control their layout.  (This was due to some other requirements I won’t cover here.  The same scripting below would work on the default LFWP with a few tweaks.)  There were several more changes which the client wanted to make to those forms:

  • The client had offices in the US and UK, so whatever the date format, it confused half the population, so they wanted to require use of the date picker control rather than allowing direct date entry.
  • They wanted to cleanly track PTO within calendar years, so no one request could cross year boundaries.
  • Start Date and End Date were required, but also should indicate a valid range.

Let’s focus on the second bullet above.  I added my helper functions to the page by including a source .js file to it.  I usually create a Document Library at the root of the Site Collection called JavaScript to contain these files for centralized editing and reuse.  So in the page, I added the following script tag:

<asp:Content ContentPlaceHolderId=”PlaceHolderAdditionalPageHead” runat=”server”>
    <META Name=”CollaborationServer” Content=”SharePoint Team Web Site”>
    <script type=”text/javascript” src=”/JavaScript/Utilities.js”></script>

Note the location of this script tag: right at the top of the asp:Content area called PlaceHolderAdditionalPageHead.

Next, I added in the code which was specific to the page directly, taking advantage of my helper functions.  (In the code below, I’ve included my helper functions inline to make following along easier.  I also have left in some commented out debugging lines which I’ve found helpful to understand exactly what’s going on.  This example is from NewForm.aspx.)

// Validate the PTO Request input
function validateInput() {
    startDate = getValueWithFieldName('input', 'Request Start Date', 'ff1_new');
    endDate = getValueWithFieldName('input', 'Request End Date', 'ff2_new');
    //alert(startDate + endDate);
    startYear = startDate.substring(startDate.length, startDate.length - 4);
    endYear = endDate.substring(endDate.length, endDate.length - 4);
    //alert(startYear + endYear);
    if(startYear != endYear) {
        return 'Start date and end date must be in the same year.  To enter a PTO request which crosses into the next year, please enter two requests.';
    }
    if(startDate.length == 0) {
        return 'Please enter a start date.';
    }
    if(endDate.length == 0) {
        return 'Please enter an end date.';
    }
    return '';
} 

// getValueWithFieldName: Get a form field value using its tagName, fieldname, and identifier to find it in the page
// Arguments:
//        tagName:    The type of input field (input, select, etc.)
//        fieldName:    The name of the list column
//        identifier:    The identifier for the instance of the fieldName (ff1, ff2, etc.)
//
    function getValueWithFieldName(tagName, fieldName, identifier) {
        //alert('getValueWithFieldName: tagName=' + tagName + ' fieldname=' + fieldName + ' identifier' + identifier);
        var theInput = getTagFromIdentifierAndFieldname(tagName, fieldName, identifier);
        //alert('getValueWithFieldName: theInput.id=' + theInput.id + ' theInput.value=' + theInput.value);
        return theInput.value;
    } 

// getTagFromIdentifierAndFieldname: Get an input field's tag object using its tagName, fieldname, and identifier to find it in the page
// Arguments:
//        tagName:    The type of input field (input, select, etc.)
//        fieldName:    The name of the list column
//        identifier:    The identifier for the instance of the fieldName (ff1, ff2, etc.)
//
    function getTagFromIdentifierAndFieldname(tagName, fieldName, identifier) {
        //alert('getTagFromIdentifierAndTitle: tagName=' + tagName + ' fieldname=' + fieldName + ' identifier' + identifier);
        var len = identifier.length;
        var tags = document.getElementsByTagName(tagName);
        for (var i=0; i < tags.length; i++) {
            if (tags&#91;i&#93;.title == fieldName) {
                //alert('HIT tags&#91;' + i + '&#93;.title' + tags&#91;i&#93;.title + ' tags&#91;' + i + '&#93;.id=' + tags&#91;i&#93;.id + ' identifier=' + identifier);
                if((tags&#91;i&#93;.id == identifier) || (tags&#91;i&#93;.id.indexOf(identifier) > 0)) {
                    return tags[i];
                }
            }
        }
        return null;
    }

In my form, I altered the onclick event on the Submit button, like so:

<td nowrap="" class="ms-vb">
    <input type="button" value="Submit" name="btnSubmit">
     <xsl:attribute name="onclick">
      errmsg = validateInput();
      if(errmsg.length > 0) {
       alert(errmsg);
      } else {
       <xsl:value-of select="ddwrt:GenFireServerEvent('__commit;__redirectsource')" />
      }
     </xsl:attribute>
    </input>
    <input type="button" value="Cancel" name="btnCancel" onclick="javascript: {ddwrt:GenFireServerEvent('__cancel;__redirectsource')}" />
   </td>

The validateInput JavaScript function does three tests:

  • Ensures that Start Date and End Date fall in the same year
  • Ensures that the Start Date is not blank
  • Ensures that the End Date is not blank

If any of these tests fails, the function returns a string with a message to the user.  The script on the button’s onclick event then either shows an alert with that message or commits the change if all is well.  The same approach works on the EditForm.aspx page, with a few tweaks to take into account the slightly different structure of the LFWP or DVWP.

Similar Posts

27 Comments

  1. Figured it out. I had to change the title, which is generated:

    CategorySelect = getValueWithFieldName(‘select’, ‘Category: Choice Drop Down’, ‘ff4_new’);
    CategoryInput = getValueWithFieldName(‘input’, ‘Category : Specify your own value:’, ‘ff4_new’);
    if((CategorySelect.length == 0) && (CategoryInput.length == 0)) {
    return ‘Category must be entered’;
    }

  2. Hi Marc. Am having problems with trying to get text from a texbox. I have used the following code, but always get an error of ‘Value’ is null or not an object on the line ‘return theInput.value;’

    var containmentText = getValueWithFieldName(“input”,”Containment”,”ff13_Edit”);

    the field is called Containment, and its reference in sharepoint is as follows:

  3. Hi Marc .
    I have a problem of validating on data obtained from another list.
    currently working on project management so i have list name project details and project task.
    the project details has the fields start date and end date and the project task has the fields start date and end date.
    so i select the the project name in the project task list thru look-up and obtain the start date and end date of the project but i am nt able to validate against the start date and end date of project task dates.

  4. How do I Valdiate two numeric field in Custom SharePoint list form.
    I have two fields Available Minutes and Required Minutes column, when the required minutes exceeds the availbale minutes the compare validator is showing error message but if the user accidently press ok it will not let the user to submit the form. everything works perfect so far. From here when they try to correct the error and resubmit the form all the field becomes null and nothing is submitted. So is there a way to show the “OK” only after all the form fileds are validated?
    or as soon the value exceeded is it possible to show an alert.

  5. Hello Marc,

    is it possible to add a redirect to the following submit button you configured for presave?

            <td nowrap="nowrap" class="ms-vb">
           <input type="button" value="Submit" name="btnSubmit" style="margin-right:5px">
             <xsl:attribute name="onclick">
              errmsg = validateInput();
              if(errmsg.length > 0) {
               alert(errmsg);
              } else {
               <xsl:value-of select="ddwrt:GenFireServerEvent('__commit;__redirectsource')" />
              }
             </xsl:attribute>
            </input>
            <input type="button" value="Cancel" name="btnCancel" onclick="javascript: {ddwrt:GenFireServerEvent('__cancel;__redirectsource')}" />  </td>
          <td nowrap="nowrap" class="ms-vb" width="99%">
           <!--
           <input type="button" value="Cancel" name="btnCancel" onclick="javascript: {ddwrt:GenFireServerEvent('__cancel')}" />
           -->
          </td>
    

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.