Posted on:
Categories: Office 365;SharePoint
Description:

Client-side rendering (CSR) has been introduced by Microsoft with SharePoint 2013 and Office 365. With CSR you can add additional functionality to some SharePoint elements very easily by just adding a JavaScript file which implements the missing functionality. There is neither an explicit deployment process nor any WSP deployment!

When looking at fields in SharePoint lists and libraries, CSR can be used to change the way fields and their values are rendered. A common example is to render a project status not to be displayed as a percentage value, but as a coloured status indicator.

But there is much more that can be done with CSR. An additional example is to add custom validation code to fields in a SharePoint list. Although fields already provide a few basic validators (like the 'required' validator or some number field validators), sometimes additional validators are needed. In this blog post I want to explain how to implement a basic CSR validator. For my example I'm using a field which should hold Canadian ZIP codes.

CSR basically works like this: instead of SharePoint rendering a field, the rendering is done by custom JavaScript code. The basic idea in terms of validators is this: if the rendering is done by custom JavaScript code, this code can perform a validation as well.

Let's have a look at the code:

In my example I created a basic generic list (called CSR Validation) with an additional field called MyField which is of type Text and should hold Canadian ZIP codes (as an example). First a code section is needed to define in what forms of a list or a library the validation should be used. In my example the validation should be added to the NewForm and the EditForm as both forms allow for entering or editing data.

 

(function () { 
    //Define field and forms that should be used
    var myFieldCtx = {}; 
    myFieldCtx.Templates = {}; 
    myFieldCtx.Templates.Fields = { 
        "MyField": { 
                    "NewForm":MyFieldTemplate, 
                    "EditForm":MyFieldTemplate                                                             
  }
    };

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(myFieldCtx);
})();
 

 

The following code snippet handles the custom rendering. Currently it just returns the HTML code for rendering the MyField text field and the additional error message placeholder. I will add the validator initialization later – that's what the ToDo comment will be used for.

 

// This function provides the rendering logic 
function MyFieldTemplate(ctx) { 

    var formCtx = SPClientTemplates.Utility.GetFormContextForCurrentField(ctx);
 
    // ToDo: Link validation to field between these lines 
    // --------------------------------------------------
 
 
    // --------------------------------------------------
    // ToDo: Link validation to field between these lines 

    // Perform the custom field rendering
    var htmlString1 = "<span dir='none'>";
    var htmlString2 = "<input type='text' value='" + formCtx.fieldValue + "' maxlength='7' id='MyField' class='ms-long'><br>";
    var htmlString3 = "<span id='myFieldValidationError' class='ms-formvalidation ms-csrformvalidation'>";
    var htmlString4 = "</span></span>";
    return htmlString1.concat(htmlString2, htmlString3, htmlString4);
}

 

Let's first check if the custom rendering is working as expected.

I add the above code to a new text file, name it MyFieldValidation.js and save it to the Style Library. After I have checked in the file, I need to remember its URL, because it is needed in the next step.

Next I navigate to the list and open the NewForm. I turn the NewForm page into edit mode, open the web part properties and paste the URL (best practice is to use tokens like ~sitecollection) of my JavaScript file into the JS Link field in the webpart properties. To have the validation in the EditForm too I need to repeat these steps for the EditForm.

The following screenshot shows where to find the JS Link field in the webpart properties:

 

The field in both forms should now be rendered as expected.

Now I'm going to add additional validation code. To do so I simply append the following snippet to the existing code:

 

// Custom validation object to validate the field 
MyFieldValidator = function() { 
 MyFieldValidator.prototype.Validate = function (value) { 
  var errorOccurred = false; 
  var errorMessage = ""; 

  // Canadian ZIP code format Regex expression 
  var zipRegex = new RegExp("[ABCEGHJKLMNPRSTVXY]\\d[A-Z] \\d[A-Z]\\d"); 
  
  if (!zipRegex.test(value)) { 
   errorOccurred = true; 
   errorMessage = "Invalid ZIP code";
  } 
  
  //Send error message to error callback function 
  return new SPClientForms.ClientValidation.ValidationResult(errorOccurred, errorMessage);
    }; 
}; 

// Add error message to myFieldValidationError element below the input field element 
function MyFieldValidationError(error) {
    document.getElementById("myFieldValidationError").innerHTML = "<span role='alert'>" + error.errorMessage + "</span>"; 
}
 

The above code snippet provides the function which performs the validation based on a RegEx expression. In addition it also provides the function (called MyFieldValidationError) which displays an error message if the validation fails.

To finish this example I need to register the validator function and its callback function and I need to link the validator to the text field. To do that, the following code snippet needs to be added between the two ToDo comments:

 

    // ToDo: Link validation to field between these lines 
    // --------------------------------------------------
 
    // Register a callback just before submit.
    formCtx.registerGetValueCallback(formCtx.fieldName, function(){ 
        return document.getElementById("MyField").value;
    });
 
    // Create container which is handling the new validator
    var validators = new SPClientForms.ClientValidation.ValidatorSet();
    validators.RegisterValidator(new MyFieldValidator());
 
    // This handler is called if the validation fails
    formCtx.registerValidationErrorCallback(formCtx.fieldName, MyFieldValidationError);
 
    // Link the validator with the field 
    formCtx.registerClientValidator(formCtx.fieldName, validators);
 
    // --------------------------------------------------
    // ToDo: Link validation to field between these lines 

 

That's all the code needed for my example. I save it and I also clear the browser cache!

Let's see if the validation works as expected. First I enter a wrong ZIP code and the validator shows the expected error message when clicking on the Save button.

 

Now I enter a correct Canadian ZIP code and the validator does not display an error message. The new item is added to the list. 

 

I think the main advantages of CSR and CSR validation are that CSR can be done with common JavaScript code and that CSR does not need any kind of deployment process (like common SharePoint solutions). CSR is a very flexible and versatile functionality and it is perfect for customizing the UI in SharePoint and Office 365. There is one disadvantage you should keep in mind: this validation will only check data that gets entered through the user interface. If data is entered by code via APIs, this kind of validation will not be able to check the data.

You can download the demo script here.