How to Use JSLink in SharePoint and Office 365

JSLink
files have the ability to quickly and easily change how a list views and forms are rendered. More specifically: how the fields in that list should be displayed.

„JSLink, on the other hand, is a property available on many SharePoint objects, including Fields, Lists, Views, and Content Types. In its simplest form, the JSLink property simply adds a JavaScript file to the page. Depending on the JavaScript, this could then do anything – either related to the object to which it was attached, or something completely unrelated, if desired.

How JSLink works:

SharePoint rendering systems (XSLT in 2010 and CAML in 2007), CSR is client-side. The only thing server-side web parts do is put a huge amount of raw data into the page, in JSON format. This data become JS object when the page loads, and from then on the Client Side Rendering begins. 

So basically, what CSR does is take the JS object with raw data as input, then renders a huge HTML string based on it: 

After the HTML string
is fully formed, it is inserted into the DOM.

Client Site Rendering
processing of the raw data is divided into stages, each represented by one overrideable JS function.  Each function returns its own chunk of HTML. Stages are often nested into each other.

The stages order isn’t documented, so head first into the clienttemplates.debug.js file to figure it out. For list views, the order turns out to be the following:

Group, Item and Field functions can
be called many times, while View, Header, Body and Footer are called only
once. 

Challenge

How do I create a custom List, custom List View, as well as content related to a custom display field and forms, lookup fields as cascading Drop-Downs (single-select) or checkboxes (multi-select) in SharePoint and Office 365, using the Visual Studio 2012 project template?

Solution

1.    Custom client-side rendered view of a custom list

To create a project template, follow these steps:

  • Open Visual Studio 2012, click New on the File menu, and then click Project.
  • In the Templates pane, select the Office/SharePoint/Apps project template under SharePoint 2012 templates folder.
  • In theName box, provide a name for your solution.

    In the Name box, input CustomListView and then click OK:

At this point, the SharePoint Customization Wizard will appear:

 

  • You will see a SharePoint Customization Wizard asking for alocal site for debugging and deployment. Enter the URL for the SharePoint server site where you want to debug the site definition, or use the default location (http://system name/).
  • Select SharePoint-hosted
    for”How do you want to host your app for SharePoint?”
  • Click Finish. The project appears in Solution Explorer.

A
new solution will be created as shown in the image below. Pages, Scripts, Features and Package folders are created, too:

 

Step1: Create
custom list

Create a list by adding a new item to the project.

Enter the name of SharePoint® list that you want to create and click on Add. It will open the wizard to choose the list settings:

 

Use the default (Blank) template to create the list and click finish:

Then choose Finish.

–         
The wizard creates a CustomList list template with a child list instance named CustomListInstance. A list designer may open. It is used in a later step.

–          Expand the CustomListInstance node in Solution Explorer, if it isn’t already, so that you can clearly distinguish the elements.xml file that is a child of the list instance from the elements.xml file that is
a child of the list template.

Lists node in
Solution Explorer:

–         
Open
the elements.xml child of the CustomList list template.

–          Add spaces to the DisplayName attribute (not the Name
attribute) to make it friendlier: “CustomList”.

–          Set the Description attribute to ” My List Definition.”

–          Leave all other attributes at their default, save the
file and close it.

–          If the list designer is not open, choose the CustomList node in Solution Explorer.

–          Open the List tab of the designer. This tab is used to set certain
values for the list instance, not the list template, but it has some default values that it inherited from the template.

–          Change the values on this tab to the following:

                            o   Title: CustomList

                            o   List URL: Lists/CustomList

                            o   Description: My List Instance.

Leave the check boxes at their default status, save the file, and close the designer

Open the schema.xml file create custom view with 

 :

 

–          Save and close the schema.xml file.

–         
Open the elements.xml file that is a child of the list instance CustomListInstance (not the elements.xml that is a child of the list template CustomList).

–         
In this file, populate the list with some initial data. You do this by adding the following Data element markup as a child element of the ListInstance element:

 

–         
Save and close the file.

–         
To add a JavaScript file for the rendering logic of the custom view

+ Right-click the Scripts folder in solution project, and add a new JavaScript file. Name the JavaScript file
CSRListView.js, which contains the rendering logic:

 

You can provide custom logic to control the
rendering process of different template sets, such as the header, footer, or
individual items in the list and code as show in the
following:

You can see more details about the format of CSRListView.js file here.

–         
After that open the schema.xml file again at BaseViewID=”2″, under the <JSLink> element we need to replace “clienttemplates.js” by “~site/Scripts/CSRListView.js”
and then Save and close the
file.

Run and test the sample

o    Press F5 to run and deploy the project.

o    Provide a title for the list in the dialog box

You can see that the data has been added to the list instance and display in custom view as shown in the following:

2.    Custom client-side rendered form view: New, Edit, Display Form and Lookup Field.

This sample demonstrates how to make some fields dependent from each other in SharePoint list item New and Edit forms. So e.g. if you change a value in one field, another field changes it’s appearance or number of variants, etc.

 

Do the same as section 1 (Custom client-side rendered view of a custom list) create new project with name is Scenario.JSLink as shown in the following:

-          Next step, create folder Lists and add new two custom list in the order named are Color and Trademark

–         
 Open the elements.xml file that is a child of the list instance ColorInstance
and populate the list with some initial data:

+
ColorInstance : 

 

+ TrademarkInstance:

 

–         
At Lists folder continue create custom list with name is LookupField:


At Schema.xml file, Be sure you have found the matching begin and end tags for the <Fields> element. Add line breaks to improve readability:

 

 

–         
Next step, right click Scenario.JSLink project and Add new item/Module with name is “Style Library”:


–         
At “Style Library” create a new folder with the name “LookupField” and add new lookup.js file:


 

–          Copy the following code and paste it in the JavaScript file. The code performs the following tasks:

o  
Get
lookup value from Trademark and Color list and rendering control drop down list and checkbox for single value and multiple value.

o  
Creates
a template for the field when it is displayed in a view , display, edit form.

 

//
create namespaces for our Display Templates

var jslinkTemplates = window.jslinkTemplates || {};

jslinkTemplates.Lookups = {};

jslinkTemplates.Lookups.Normal = {};

jslinkTemplates.Lookups.Normal.SingleItem = {};

jslinkTemplates.Lookups.Normal.MultiItem = {};

 

jslinkTemplates.Lookups.registerCallBack = function (ctx) {

    var formCtx =
SPClientTemplates.Utility.GetFormContextForCurrentField(ctx);

 

    // registers the callback for
the specified field

    if (ctx.CurrentFieldSchema.Type
== “Lookup” &&

       
ctx.CurrentFieldSchema.FieldType == “Lookup”) {

       
formCtx.registerGetValueCallback(formCtx.fieldName,
jslinkTemplates.Lookups.getSingleValue.bind(null, formCtx.fieldName));

    }

    else if
(ctx.CurrentFieldSchema.Type == “Lookup” &&

       
ctx.CurrentFieldSchema.FieldType == “LookupMulti”) {

       
formCtx.registerGetValueCallback(formCtx.fieldName,
jslinkTemplates.Lookups.getMultiValue.bind(null, formCtx.fieldName));

    }

};

 

jslinkTemplates.Lookups.getMultiValue = function (fieldName) {

    // returns the value of our
multi-lookup field

    //debugger;

    var returnValue = ”;

 

    // get the values we want

    var checkboxes =
$(“#” + fieldName + “LookupValues input[type=checkbox]:checked”);

    //var checkboxes =
$(“input[type=checkbox]:checked”);

 

    for (var i = 0; i <
checkboxes.length; i++) {

        if (returnValue != ”) {

            returnValue += ‘;#’

        }

 

        returnValue +=
checkboxesIdea.value;

    }

 

    return returnValue;

};

jslinkTemplates.Lookups.getSingleValue = function (fieldName, textOnly) {

    // returns the value of our
single-item lookup field

    // option to just return the
text value

    //debugger;

    var selectedValue =
$(“#” + fieldName + “LookupValues option:selected”);

 

    if (selectedValue[0]) {

 

        if (textOnly) {

            return
selectedValue[0].innerText;

        }

        else {

            return
selectedValue[0].value;

        }

    }

    else {

        return null;

    }

};

 

jslinkTemplates.Lookups.Normal.SingleItem.editForm = function
(formContext) {

    //debugger;

    var queryStringId =
jslinkTemplates.Lookups.getQuerystring(formContext.CurrentFieldSchema.Name);

    // we need this if we use the
looking as a cascading drop-down anywhere

   
jslinkTemplates.Lookups.registerCallBack(formContext);

    var returnHtml = “<div
id='” + formContext.CurrentFieldSchema.Name +
“LookupValues’>”;

    returnHtml +=
“<select”;

    if (queryStringId !=
“”) {

        returnHtml += ”
disabled=’true’ title=’You cannot change this field'”;

    }

    returnHtml += “>”;

 

    if
(!formContext.CurrentFieldSchema.Required) {

        returnHtml +=
“<option value=””;

 

        if
(formContext.CurrentFieldValue == “”) {

            returnHtml += ”
selected=’true'”;

        }

        returnHtml +=
“>(None)</option>”;

    }

    var choices =
formContext.CurrentFieldSchema.Choices;

 

    for (var i = 0; i <
choices.length; i++) {

        var lookupString =
choicesIdea.LookupId + “;#” + choicesIdea.LookupValue;

        returnHtml +=
“<option value='” + lookupString + “‘”;

 

        if (choicesIdea.LookupId ==
queryStringId) {

            returnHtml += ”
selected=’true'”;

        }

        else if
(formContext.CurrentFieldValue == lookupString) {

            returnHtml += ”
selected=’true'”;

        }

 

        returnHtml +=
“>” + choicesIdea.LookupValue + “</option>”;

    }

 

    returnHtml +=
“</select></div>”;

 

    return returnHtml;

}

 

jslinkTemplates.Lookups.Normal.MultiItem = function (formContext) {

   
//debugger;

   
jslinkTemplates.Lookups.registerCallBack(formContext);

    //var formCtx =
SPClientTemplates.Utility.GetFormContextForCurrentField(formContext);

    var choices =
formContext.CurrentFieldSchema.Choices;

    var returnHtml = “<div
id='” + formContext.CurrentFieldSchema.Name +
“LookupValues’>”;

    for (var i = 0; i <
choices.length; i++) {

        var choiceText =
choicesIdea.LookupValue;

        var choiceValue =
choicesIdea.LookupId + ‘;#’ + choicesIdea.LookupValue;

        returnHtml +=
“<input type=’checkbox’ name='” + choiceText + “‘
value='” + choiceValue + “‘ style=’float: left;'”;

        if
(formContext.CurrentFieldValue &&
formContext.CurrentFieldValue.indexOf(choiceValue) != -1) {

            // if the item contains
the current checkbox value then check it

            returnHtml += ”
checked “;

        }

        returnHtml +=
“/><span style=’display: block; padding-left: 25px; min-height:
20px;’>” + choiceText + “</span>”;

    }

    returnHtml +=
“</div>”;

    return returnHtml;

}

 

jslinkTemplates.Lookups.Normal.view = function (viewContext) {

    var values =
viewContext.CurrentItem[viewContext.CurrentFieldSchema.Name];

    if (values.length > 1) {

 

        var returnHtml =
“<ul style=’margin-top: 0px; margin-bottom: 0px;’>”;

        for (var i = 0; i <
values.length; i++) {

            // add a new LI element
for each value

            returnHtml +=
“<li>” + valuesIdea.lookupValue + “</li>”;

        }

 

        returnHtml +=
“</ul>”;

 

        return returnHtml;

    }

    else if (values.length == 1) {

        return
“<span>” + values[0].lookupValue + “</span>”;

    }

    else {

        return “”;

    }

};

 

jslinkTemplates.Lookups.Normal.displayForm = function (formContext) {

    //debugger;

    if (formContext.CurrentFieldValue
!= “”) {     

        var returnHtml =
“<ul style=’margin-top: 0px; margin-bottom: 0px;’>”;

        var values =
formContext.CurrentItem[formContext.CurrentFieldSchema.Name].toString();

        if (values.length > 1) {

            var choices = formContext.CurrentFieldSchema.Choices;

 

            for (var i = 0; i <
choices.length; i++) {

                if
(values.indexOf(choicesIdea.LookupValue) != -1) {

                    returnHtml +=
“<li>” + choicesIdea.LookupValue + “</li>”;

                }

            }

 

            returnHtml +=
“</ul>”;

 

            return returnHtml;

        }

    }

    else {

        return “”;

    }

};

 

 

jslinkTemplates.Lookups.getQuerystring = function (key, defaultValue) {

    if (defaultValue == null)
defaultValue = “”;

    key = key.replace(/[[]/,
“[“).replace(/[]]/, “]”);

    var regex = new
RegExp(“[?&]” + key + “=([^&#]*)”);

    var qs =
regex.exec(window.location.href);

    if (qs == null)

        return defaultValue;

    else

        return qs[1];

};

 

–          Save and close the file.

–          Next, create new folder named “TemplateOverrides” in the  “Style Library” folder and add LookUpOverrides.js file:

 

–          And then copy the following code and paste it in the JavaScript file. The code performs the following tasks:

o    Creates a template for the field when it is displayed in a view form, new form, edit form, display form

o    Registers the template.

o    Provides the rendering logic for the field type when used displayed in a view form, new form, edit form, display form.

–         
Save
and close the file.

Run and test the sample

o    Press F5 to run and deploy the project.

You can see that the data has been added to the list instance and display as shown:

+ Screenshot below indicates for new item:  

 

+ View form:

 

+ Display Form:


 

+ Edit form:

 

3.    This is a simple color picker scenario with all of the HTML colors rendering in a drop-down list, with the actual color being shown in the View and Display Form.

 

–         
Do the same section 1 and 2 : In Lists folder create custom list with name ColorPicker:

At Schema.xml file, be sure you have found the matching begin and end tags for the <Fields> element. Add line breaks to improve readability:

 

–    And following
code in the JavaScript file to rendering drop down list get colors:

 

var jslinkTemplates =
window.jslinkTemplates || {};

 

jslinkTemplates.Colours =
function () {

 

    var selectIdPrefix = “COL_”;

    var errorIdPrefix = “ERR_”;

 

    var display = function (ctx) {

 

        // return our string

        return
getColourSpan(ctx.CurrentItem[“Colour”]);

    };

    var edit = function (ctx) {

 

        // create form context object

        var formCtx =
SPClientTemplates.Utility.GetFormContextForCurrentField(ctx);

 

        // register our custom validator

        var validator = new
SPClientForms.ClientValidation.ValidatorSet();

        validator.RegisterValidator(new
jslinkTemplates.Colours.validator());

       
formCtx.registerClientValidator(formCtx.fieldName, validator);

 

        // register our callbacks

       
formCtx.registerGetValueCallback(formCtx.fieldName,
jslinkTemplates.Colours.getValue.bind(null, formCtx.fieldName));

       
formCtx.registerValidationErrorCallback(formCtx.fieldName,
jslinkTemplates.Colours.onError.bind(null, formCtx.fieldName));

 

        var returnHtml = “”;

        //#region array of available colours

        var colours = new
Array(“AliceBlue”,

                               
“AntiqueWhite”,

                               
“Aqua”,

                               
“Aquamarine”,

                               
“Azure”,

                               
“Beige”,

                               
“Bisque”,

                               
“Black”,

                               
“Turquoise”,

                               
“Violet”,

                                “Wheat”,

                               
“White”,

                               
“WhiteSmoke”,

                               
“Yellow”,

                               
“YellowGreen”);

        //#endregion

 

        returnHtml += “<select
id='” + selectIdPrefix + formCtx.fieldName + “‘>”;

        for (var i = 0; i < colours.length;
i++) {

            // create a drop-down option

            returnHtml += “<option
value='” + coloursIdea + “‘”;

 

            if (ctx.CurrentItem[“Colour”]
== coloursIdea) {

                // make sure the current field
value is selected

                returnHtml += ”
selected=’true’ “;

 

            }

            returnHtml += “>” +
getColourSpan(coloursIdea) + “</option>”;

        }

        returnHtml +=
“</select>”;

 

        // add an error span for our validator
to use

        returnHtml += “<br/><span
id='” + errorIdPrefix + formCtx.fieldName + “‘
class=’ms-formvalidation
ms-csrformvalidation’></span><br/>”;

 

        return returnHtml;

    };

 

    var getColourSpan = function (colour) {

        var returnHtml = “”;

        returnHtml += “<div
style=’background: ” + colour + “; width: 20px; float:
left’>&nbsp;</div>”;

        returnHtml += “<div
style=’margin-left: 30px;’>” + colour + “</div>”;

 

        return returnHtml;

    };

 

    var getValue = function (fieldName) {

        var selector = ‘#’ + selectIdPrefix +
fieldName;

        return $(selector).val();

    };

    var validator = function () {

        jslinkTemplates.Colours.validator.prototype.Validate
= function (value) {

            var isError = false;

            var errorMessage = “”;

 

            if (value == “Blue”) {

                isError = true;

                errorMessage = “Sorry, we
don’t like the colour blue”;

            }

 

            return new
SPClientForms.ClientValidation.ValidationResult(isError, errorMessage);

        };

    };

    var onError = function (fieldName, error) {

        var selector = ‘#’ + errorIdPrefix +
fieldName;

        $(selector).html(“<span role=’alert’>”
+ error.errorMessage + “</span>”);

    };

 

    return {

        “display”: display,

        “edit”: edit,

        “getValue”: getValue,

        “validator”: validator,

        “onError”: onError

    }

}();

–         
Save
and close the file.

–          Next, create new folder name is “TemplateOverrides” in “Style Library” folder and add FavouriteColours.js file as follows:

–          And then copy the following code and paste it in the JavaScript file. The code performs the following tasks:

o    Creates a template for the field when it is displayed.

o    Registers the template.

o    Provides the rendering logic for the field type and this also includes an example of a “Validator” where you can control validation of data entry through the SharePoint Client Site Rendering techniques.

Run and test the sample

o    Press F5 to run and deploy the project.

You can see that the data has been added to the list instance and display as shown in the following figure

+ New item:

+
Display Form:


 

  + View Form:


Our final solution structure should now look like the following figure:

All done! Our solution is now ready to publish into a .app file and deployment into the SharePoint app and Office 365.

You can download a demo project here.

I hope you found it helpful to learn how to create a more full-featured JsLink, incorporating several features and elements you may wish to add.

All SharePoint Versions

The web parts are functional components that extend your SharePoint environment whether it’s hosted, on-premises, or part of Microsoft® Office 365.

SharePoint 2013, 2016, 2019, Online (Office 365)

On-Premises Only

These web parts extend SharePoint beyond its out-of-the-box capabilities by tailoring it to your requirements with Bamboo Solution’s growing portfolio of SharePoint Web Parts.

SharePoint 2013, 2016, 2019

SharePoint

Product Suites

Experience greater power and savings by bundling our SharePoint apps and web parts.


Essentials Suite


Essentials Plus Suite


Bamboo Premier Suite


Project Management Suite


Knowledge Management Suite


External User Manager


 

For more information on our product suites, contact us.

Featured Services

SharePoint Health Check

A SharePoint Health Check will identify the causes of issues and risks associated with your specific environment, and is custom tailored to provide you with the best recommendations to optimize your SharePoint environment.

SQL Health Check

Document recommendations relating to performance, stability, availability, or a specific focus you request of your SQL Server database instances.

My SharePointXperts

The truth is that each SharePoint skill may not be a full time job for many organizations, and it is nearly impossible for one person to do everything you need – so augment your team with SharePointXperts; providing the skill sets you need when you need them!