My Idea Factory - By Ludovic Perrichon

SharePoint, JavaScript, JSLink, Forms

Custom SharePoint form with JSLink

I had to do custom designed and business rules on SharePoint Forms.
I started with example from the following link : https://code.msdn.microsoft.com/office/Client-side-rendering-JS-2ed3538a.

In this article, I am going to show you utilities functions I use. The idea is to do custom designed forms.

  1. Setting example SharePoint list
  2. Setting form view
  3. JS utilities
  4. All JSLink
  5. What it looks like

Setting example SharePoint list

I have a SharePoint list with the following columns:

Column nameColumn typeDefault value
TitleString-
DateDate-
UnlockForm2BooleanFalse
CommentsMultiple line-
WasItEasyChoiceFingers in the nose

Setting form view

So far my list is looking to this:

Let's prepare your view for the JSLink. Edit your page then edit the webpart properties of the form.

In miscellaneous part, change the properties like this:

JS Utilities

Let's start to do some Javascript. Well the idea in the forms is to get fields display name, to still be able to change the display name through the list settings, or to get value of each fields.

var JSLinkForm = JSLinkForm || {};

JSLinkForm.Utils = {  
    // Render SharePoint input field
    getSPFieldRender : function(ctx, fieldName)
    {
        var fieldContext = ctx;

        //Get the filed Schema
        var result = ctx.ListSchema.Field.filter(function( obj ) {
            return obj.Name == fieldName;
        });

        fieldContext.CurrentFieldSchema = result[0];
        fieldContext.CurrentFieldValue = ctx.ListData.Items[0][fieldName];

        return ctx.Templates.Fields[fieldName](fieldContext);
    },
    // Get field value
    getSPFieldValueForFom : function(ctx, fieldName){
        //Get the filed Schema
        var result = ctx.ListSchema.Field.filter(function( obj ) {
            return obj.Name == fieldName;
        });

        ctx.CurrentFieldSchema = result[0];
        ctx.CurrentFieldValue = ctx.ListData.Items[0][fieldName];

        var hideField = ctx.Templates.Fields[fieldName](ctx);

        // Add the field in display none, otherwise it will set the field value to null or empty.
        // Which means in edit forms, when you save, it will change your current value to empty.
        return ctx.ListData.Items[0][fieldName] + '<div style="display:none;">'+ hideField + '</div>';
    },
    getSPFieldValue : function(ctx, fieldName){
        return ctx.ListData.Items[0][fieldName];
    },
    // Get field label
    getSPFieldLabel : function(ctx, fieldName){
        var allFields = ctx.ListSchema.Field;
        var required = false;
        var label = "<span color='red'>Canno't find the label</span>";

        for(var i = 0; i < allFields.length; i++){
            var fieldInfo = allFields[i];
            if(fieldInfo.Name == fieldName){
                label = fieldInfo.Title;
                required = fieldInfo.Required;
                break;
            }
        }

        if(required){
            label += '<span title="This field is mandatory." class="ms-accentText"> *</span>';
        }

        return label;
    }
};

In this script, I am going to use the functions above. The goal is, if UnlockForm2 is checked and if the date is less or equal than today, then edit the fields WasItEasy and Comments. Otherwise do not edit it.

Of course this Javascript need to be saved in a file and uploaded in SharePoint.

var JSLinkForm = JSLinkForm || {};

JSLinkForm.Utils = {  
    // Render SharePoint input field
    getSPFieldRender : function(ctx, fieldName)
    {
        var fieldContext = ctx;

        //Get the filed Schema
        var result = ctx.ListSchema.Field.filter(function( obj ) {
            return obj.Name == fieldName;
        });

        fieldContext.CurrentFieldSchema = result[0];
        fieldContext.CurrentFieldValue = ctx.ListData.Items[0][fieldName];

        return ctx.Templates.Fields[fieldName](fieldContext);
    },
    // Get field value
    getSPFieldValueForFom : function(ctx, fieldName){
        //Get the filed Schema
        var result = ctx.ListSchema.Field.filter(function( obj ) {
            return obj.Name == fieldName;
        });

        ctx.CurrentFieldSchema = result[0];
        ctx.CurrentFieldValue = ctx.ListData.Items[0][fieldName];

        var hideField = ctx.Templates.Fields[fieldName](ctx);

        // Add the field in display none, otherwise it will set the field value to null or empty.
        // Which means in edit forms, when you save, it will change your current value to empty.
        return ctx.ListData.Items[0][fieldName] + '<div style="display:none;">'+ hideField + '</div>';
    },
    getSPFieldValue : function(ctx, fieldName){
        return ctx.ListData.Items[0][fieldName];
    },
    // Get field label
    getSPFieldLabel : function(ctx, fieldName){
        var allFields = ctx.ListSchema.Field;
        var required = false;
        var label = "<span color='red'>Canno't find the label</span>";

        for(var i = 0; i < allFields.length; i++){
            var fieldInfo = allFields[i];
            if(fieldInfo.Name == fieldName){
                label = fieldInfo.Title;
                required = fieldInfo.Required;
                break;
            }
        }

        if(required){
            label += '<span title="This field is mandatory." class="ms-accentText"> *</span>';
        }

        return label;
    }
};

JSLinkForm.Forms = {  
    form1 : function(ctx){
        var strHtml = '<div class="title active">Enter data</div>';
        strHtml += '<table class="panel" style="display:block;">';
        strHtml += '<tr>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldLabel(ctx, "Title") +' : </td>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldRender(ctx, "Title") +'</td>';
        strHtml += '</tr>';
        strHtml += '<tr>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldLabel(ctx, "Date") +' : </td>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldRender(ctx, "Date") +'</td>';
        strHtml += '</tr>';
        strHtml += '<tr>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldLabel(ctx, "UnlockForm2") +' : </td>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldRender(ctx, "UnlockForm2") +'</td>';
        strHtml += '</tr>';
        strHtml += '</table>';
        strHtml += '<div  class="title">Enter Comments</div>';
        strHtml += '<table class="panel">';
        strHtml += '<tr>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldLabel(ctx, "Comments") +' : </td>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldValueForFom(ctx, "Comments") +'</td>';
        strHtml += '</tr>';
        strHtml += '<tr>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldLabel(ctx, "WasItEasy") +' : </td>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldValueForFom(ctx, "WasItEasy") +'</td>';
        strHtml += '</tr>';
        strHtml += '</table>';
        return strHtml;
    },
    form2 : function(ctx){
        var strHtml = '<div class="title">Enter data</div>';
        strHtml += '<table class="panel">';
        strHtml += '<tr>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldLabel(ctx, "Title") +' : </td>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldValueForFom(ctx, "Title") +'</td>';
        strHtml += '</tr>';
        strHtml += '<tr>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldLabel(ctx, "Date") +' : </td>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldValueForFom(ctx, "Date") +'</td>';
        strHtml += '</tr>';
        strHtml += '<tr>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldLabel(ctx, "UnlockForm2") +' : </td>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldValueForFom(ctx, "UnlockForm2") +'</td>';
        strHtml += '</tr>';
        strHtml += '</table>';
        strHtml += '<div class="title active">Enter Comments</div>';
        strHtml += '<table class="panel">';
        strHtml += '<tr>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldLabel(ctx, "Comments") +' : </td>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldRender(ctx, "Comments") +'</td>';
        strHtml += '</tr>';
        strHtml += '<tr>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldLabel(ctx, "WasItEasy") +' : </td>';
        strHtml += '<td>'+ JSLinkForm.Utils.getSPFieldRender(ctx, "WasItEasy") +'</td>';
        strHtml += '</tr>';
        strHtml += '</table>';
        return strHtml;
    },
    saveBtn : function(ctx){
        var strHtml = '<table>';
        strHtml += "<tr>";
        strHtml += "<td><input type='button' value='Enregistrer' onclick=\"SPClientForms.ClientFormManager.SubmitClientForm('"+ctx.FormUniqueId+"');\" style='margin-left:0' ></td>";
        strHtml += "</tr>";
        strHtml += '</table>';

        return strHtml;
    }
};

JSLinkForm.FormTemplate = function(ctx){  
    var unlock = JSLinkForm.Utils.getSPFieldValue(ctx, "UnlockForm2");
    var date = JSLinkForm.Utils.getSPFieldValue(ctx, "Date");
    var dateArr = date.split(" ")[0].split("/");
    var strDate = dateArr[2]+''+dateArr[1]+''+dateArr[0];
    var today = new Date();
    var day = today.getDate();
    if(day < 10){
        day = '0'+ day;
    }
    var month = today.getMonth() + 1;
    if(month < 10){
        month = '0'+ month;
    }
    var year = today.getFullYear();
    var strToday = year + '' + month + '' + day;
    var strHtml = "";

    if((unlock == 1) && (parseInt(strDate) <= parseInt(strToday))){
        strHtml += JSLinkForm.Forms.form2(ctx);
    }
    else{
        strHtml += JSLinkForm.Forms.form1(ctx);
    }

    strHtml += JSLinkForm.Forms.saveBtn(ctx);

    return strHtml;
};

(function () {   
    var formTemplate = {};
    formTemplate.Templates = {};
    formTemplate.Templates.View = JSLinkForm.FormTemplate;

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(formTemplate);

})();

I have also add a script editor webpart in the new and edit forms.

<style>  
.title {
    background-color: #eee;
    color: #444;
    cursor: pointer;
    padding: 18px;
    width: 100%;
    border: none;
    font-weight: bold;
    text-align: left;
    outline: none;
    font-size: 15px;
    transition: 0.4s;
}

.active {
    background-color: #000;
    color: #fff;
}

.panel {
    padding: 0 18px;
    background-color: white;
    overflow: hidden;
}

.ms-rtestate-write{
    border: solid 1px #999;
}
</style>  

What it looks like