Blog

How to implement Validation to require Attachments in a SharePoint List Item creation in SharePoint 2013 using Client-side Rendering

One of the best improvements in SharePoint 2013 is JSLink or Client-side Rendering, because you can override the OOTB behavior of SharePoint Fields, Views, Items, New Form, Edit Form, View Form, etc.

 

In this case we’re going to implement attachment required validation in one SharePoint List.

 

 


(function () {
    _spBodyOnLoadFunctionNames.push("showAttachmentsHere");
})();

(function () {
    // Initialize the variable that stores the objects.
    var overrideCtx = {};
    overrideCtx.Templates = {};    
    overrideCtx.Templates.Fields = {
        "Attachments": {
            "NewForm": attachmentValidatorTemplate
        }
    };
    

     //overrideCtx.OnPostRender = postRenderfunc;
     
    // Register the template overrides.
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
})();

function insertAfter(referenceNode, newNode) {
    referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}

function showAttachmentsHere()
{
    var ats = document.getElementById('idAttachmentsRow');
    var table = ats.parentNode.parentNode;
    var el = document.createElement("span");
    el.innerHTML = "attach CV
"; insertAfter(table, el); } // This function provides the rendering logic function attachmentValidatorTemplate(ctx) { var formCtx = SPClientTemplates.Utility.GetFormContextForCurrentField(ctx); // Register a callback just before submit. formCtx.registerGetValueCallback(formCtx.fieldName, function () { return document.getElementById('idAttachmentsTable').rows.length; }); //Create container for various validations var validators = new SPClientForms.ClientValidation.ValidatorSet(); validators.RegisterValidator(new attachmentValidator()); // Validation failure handler. formCtx.registerValidationErrorCallback(formCtx.fieldName, attachmentOnError); formCtx.registerClientValidator(formCtx.fieldName, validators); var customAttach = ''; customAttach += ''; var finalresult = customAttach + SPFieldAttachments_Default(ctx); return finalresult; } function AttachFile2() { var instance = SP.Ribbon.PageManager.get_instance(); if (instance) instance.get_commandDispatcher().executeCommand("Ribbon.ListForm.Edit.Actions.AttachFile", null); }; // Custom validation object to validate email format attachmentValidator = function () { attachmentValidator.prototype.Validate = function (value) { var isError = false; var errorMessage = ""; if (value == 0) { isError = true; errorMessage = "You must include file attached."; } //Send error message to error callback function (emailOnError) return new SPClientForms.ClientValidation.ValidationResult(isError, errorMessage); }; }; // Add error message to spnError element under the input field element function attachmentOnError(error) { document.getElementById("spnError").innerHTML = "" + error.errorMessage + ""; }

 

References:

https://social.technet.microsoft.com/Forums/sharepoint/en-US/ef5fee21-03c7-404e-a73b-a452d4a06c47/add-attachment-field-to-post-list-in-sharepoint-2013?forum=sharepointgeneral

http://sharepoint.stackexchange.com/questions/120226/add-attachment-button-to-a-custom-new-form-sharepoint-2013

https://code.msdn.microsoft.com/office/Sample-8-List-add-and-edit-d228b751

http://sharepoint.stackexchange.com/questions/112506/sharepoint-2013-js-link-return-default-field-rendering

http://blog.ithinksharepoint.com/2014/11/17/sharepoint-2013online-attachment-viewer-enhancement/

 

 

 

HTH

JQ

@jquintozamora

19 Thoughts on “How to implement Validation to require Attachments in a SharePoint List Item creation in SharePoint 2013 using Client-side Rendering

  1. raghu on May 17, 2015 at 8:50 am said:

    Attachment field is noetrt working when i modify new form template, returning error span id part1 is not available
    Any help

    • José Quinto Zamora on May 19, 2015 at 2:12 pm said:

      Hi Raghu,
      Could you please share all your code to see in detail?

      Regards!

      • raghu on June 1, 2015 at 10:57 am said:

        Hi,

        Can your sample code to make work with attachment field in Newform, in Context am not getting attachment field object

        • José Quinto Zamora on June 1, 2015 at 1:08 pm said:

          HI Raghu,

          You need to add JSLink fie in the NewFOrm.aspx page> /Lists/TestList/NewForm.aspx

          Go to your list.
          Go to New Item
          Edit this page (/Lists/TestList/NewForm.aspx)
          Edit WebPArt Properties
          Paste your js url in CSR Render Mode (Miscellaneous category).
          Example of JS link: ~sitecollection/_catalogs/masterpage/js/jquery-1.11.3.min.js|~sitecollection/_catalogs/masterpage/js/csr/attachments.js
          Important to add ~sitecollection, otherwise won’t work.

          Regards!

          • raghu on June 4, 2015 at 7:26 am said:

            Hi,

            Thanks a lot for your replies, Only having problem with attachment field. For other fields am able to do client side rendering by adding csr js and other details

            Are you sure about attachment field object working in Newform.aspx, now am getting doubt on SP13 latest updates

  2. raghu on May 26, 2015 at 5:23 pm said:

    I have implemented Tabs using below template, how can i enable attachment field in below template

    // // List Form – Tabs Sample
    // Muawiyah Shannak , @MuShannak

    var currentFormUniqueId;
    var currentFormWebPartId;

    // Use “Multi String” javascript to embed the required css
    var MultiString = function (f) {
    return f.toString().split(‘\n’).slice(1, -1).join(‘\n’);
    }
    var tabsStyle = MultiString(function () {/**
    .tabs {
    border-bottom: 1px solid #ddd;
    content: ” “;
    display: table;
    margin-bottom: 0;
    padding-left: 0;
    list-style: none;
    width: 100%;
    }

    .tabs > li {
    float: left;
    margin-bottom: -1px;
    position: relative;
    display: block;
    }

    .tabs > li > a {
    margin-right: 2px;
    line-height: 1.42857143;
    border: 1px solid transparent;
    position: relative;
    display: block;
    padding: 10px 15px;
    }

    .tabs a {
    color: #428bca;
    text-decoration: none;
    }

    .tabs > li.active > a, .tabs > li.active > a:hover, .tabs > li.active > a:focus {
    color: #555;
    background-color: #fff;
    border: 1px solid #ddd;
    border-bottom-color: transparent;
    cursor: default;
    }

    **/
    });

    var tabsObj = [
    [“General”, [“Title”, “Age”]],
    [“Work”, [“Manager”]],
    [“Other”, [“Comments”]]
    ];

    (function () {

    // jQuery library is required in this sample
    // Fallback to loading jQuery from a CDN path if the local is unavailable
    (window.jQuery || document.write(”));

    var tabsContext = {};
    tabsContext.Templates = {};
    tabsContext.OnPreRender = TabsOnPreRender;
    tabsContext.OnPostRender = TabsOnPostRender;
    tabsContext.Templates.View = viewTemplate;

    // accordionContext.OnPostRender = accordionOnPostRender;

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(tabsContext);

    })();

    function viewTemplate(ctx) {

    var formTable = “”.concat(“”,
    “”,
    “{{TitleValNm}}”,
    “{{Title}}”,

    “”,
    “”,
    “{{AgeValNm}}”,
    “{{Age}}”,

    “”,
    “”,
    “{{ManagerValNm}}”,
    “{{Manager}}”,

    “”,
    “”,
    “{{CommentsValNm}}”,
    “{{Comments}}”,
    “”,

    “”,
    “”,
    “”,
    “”,
    “”);

    //Replace the tokens with the default sharepoint controls
    //formTable = formTable.replace(“{{Affected}}”, getSPFieldRender(ctx, “AffectedEmployee”));
    formTable = formTable.replace(“{{Title}}”, getSPFieldRender(ctx, “Title”));
    formTable = formTable.replace(“{{TitleVal}}”, getSPFieldDescriptionRender(ctx, “Title”));
    formTable = formTable.replace(“{{TitleValNm}}”, getSPFieldDescriptionRender(ctx, “Title”));

    formTable = formTable.replace(“{{Age}}”, getSPFieldRender(ctx, “Age”));
    formTable = formTable.replace(“{{AgeVal}}”, getSPFieldDescriptionRender(ctx, “Age”));
    formTable = formTable.replace(“{{AgeValNm}}”, getSPFieldDescriptionRender(ctx, “Age”));

    formTable = formTable.replace(“{{Manager}}”, getSPFieldRender(ctx, “Manager”));
    formTable = formTable.replace(“{{ManagerVal}}”, getSPFieldDescriptionRender(ctx, “Manager”));
    formTable = formTable.replace(“{{ManagerValNm}}”, getSPFieldDescriptionRender(ctx, “Manager”));

    formTable = formTable.replace(“{{Comments}}”, getSPFieldRender(ctx, “Comments”));
    formTable = formTable.replace(“{{CommentsVal}}”, getSPFieldDescriptionRender(ctx, “Comments”));
    formTable = formTable.replace(“{{CommentsValNm}}”, getSPFieldDescriptionRender(ctx, “Comments”));

    // formTable = formTable.replace(“{{SupervisorVal}}”, getSPFieldRender(ctx, “SupervisorName”));
    // formTable = formTable.replace(“{{Supervisor}}”, getSPFieldDescriptionRender(ctx, “SupervisorName”));
    // formTable = formTable.replace(“{{IncidentDateValue}}”, getSPFieldRender(ctx, “IncidentFirstReported”));
    // formTable = formTable.replace(“{{IncidentDate}}”, getSPFieldDescriptionRender(ctx, “IncidentFirstReported”));

    formTable = formTable.replace(“{{FormId}}”, ctx.FormUniqueId);
    return formTable;
    }

    //This function code set the required properties and call the OOTB (default) function that use to render Sharepoint Fields
    function getSPFieldRender(ctx, fieldName)
    {
    var fieldContext = ctx;

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

    //Set the field Schema & default value
    fieldContext.CurrentFieldSchema = result[0];
    fieldContext.CurrentFieldValue = ctx.ListData.Items[0][fieldName];

    //Call OOTB field render function
    return ctx.Templates.Fields[fieldName](fieldContext);
    }
    //This function code set the required properties and call the OOTB (default) function that use to render Sharepoint Fields
    function getSPFieldDescriptionRender(ctx, fieldName)
    {
    var fieldContext = ctx;

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

    //Set the field Schema & default value
    fieldContext.CurrentFieldSchema = result[0];
    //fieldContext.CurrentFieldValue = ctx.ListData.Items[0][fieldName];

    //Call OOTB field render function
    return fieldContext.CurrentFieldSchema.Name;
    }

    function TabsOnPreRender(ctx) {
    if (!currentFormUniqueId) {

    currentFormUniqueId = ctx.FormUniqueId;
    currentFormWebPartId = “WebPart” + ctx.FormUniqueId;

    jQuery(document).ready(function () {

    var tabHTMLTemplate = “{Title}“;
    var tabClass;
    var tabsHTML = “”;

    for (var i = 0; i < tabsObj.length; i++) {
    tabClass = "";
    if (i == 0){ tabClass = "active";}
    tabsHTML += tabHTMLTemplate.replace(/{Index}/g, i).replace(/{Title}/g, tabsObj[i][0]).replace(/{class}/g, tabClass)
    }

    jQuery("#" + currentFormWebPartId).prepend("” + tabsHTML + “”);

    jQuery(‘.tabs li a’).on(‘click’, function (e) {
    var currentIndex = jQuery(this).attr(‘href’).replace(“#”,””);
    showTabControls(currentIndex);
    jQuery(this).parent(‘li’).addClass(‘active’).siblings().removeClass(‘active’);
    e.preventDefault();
    });

    showTabControls(0);

    jQuery(“#” + currentFormWebPartId).prepend(“” + tabsStyle + “”);
    });

    }
    }

    function TabsOnPostRender(ctx) {
    var controlId = ctx.ListSchema.Field[0].Name + “_” + ctx.ListSchema.Field[0].Id;
    //jQuery(“[id^='” + controlId + “‘]”).closest(“tr”).attr(‘id’, ‘tr_’ + ctx.ListSchema.Field[0].Name).hide();

    }

    function showTabControls(index)
    {
    for(var j=0;j<tabsObj.length;j++){

    for (var i = 0; i < tabsObj[j][1].length; i++) {
    if(j==index){

    //jquery("[id^='CSR_" + tabsObj[j][1][i] + "_']").show();
    jQuery("#CSR_"+tabsObj[j][1][i]+"").show();
    }
    else{
    jQuery("#CSR_"+tabsObj[j][1][i]+"").hide();
    //jquery("[id^='CSR_" + tabsObj[j][1][i] + "_']").hide();
    }
    }
    }
    }

  3. raghu on May 26, 2015 at 5:24 pm said:

    For above code tried to registered as below , but looks like attachment field not available.
    overrideCtx.Templates.Fields = {
    “Attachments”: {
    “NewForm”: attachmentValidatorTemplate
    }
    };

    • José Quinto Zamora on June 1, 2015 at 1:05 pm said:

      Hi Raghu,
      Using JSLink, you need to decide what level you want override. I mean, If you override View Template: tabsContext.Templates.View = viewTemplate; , you can’t override Fields template at the same time “overrideCtx.Templates.Fields”.

      Hope that helps.

      • raghu on June 2, 2015 at 6:50 pm said:

        Hi

        I tried only attachment field overriding but still in the ctx, am unable to find attachment field object. Can your entire JSlink and can u share your email

      • José Quinto Zamora on June 4, 2015 at 1:59 pm said:

        Hi Raghu,
        I guess it is not triggered because 2 things:

        1. You should execute your template registration after clienttemplates.js file is rendered.
        2. The field action is NewForm instead New.

        Please, try with this code (take care with apostrophe symbol):

        (function () {
        ExecuteOrDelayUntilScriptLoaded(_registerSliderViewTemplate, ‘clienttemplates.js’);
        })();

        function _registerSliderViewTemplate()
        {
        var overrideCtx = {};
        overrideCtx.Templates = {};
        overrideCtx.Templates.Fields = {
        “Attachments”: {
        “NewForm”: attachmentValidatorTemplate
        }
        };
        // Register the template overrides.
        SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
        }

        // This function provides the rendering logic
        function attachmentValidatorTemplate(ctx)
        {
        alert(‘entered function’);
        }

        • raghu on June 9, 2015 at 7:56 am said:

          Hi,

          Thanks a lot for your replies, I tried your case by trying those 2 steps (register clienttemplates.js and NewForm) but it didn’t work. Tried in different Azure env also it didn’t.

          In this case also, when i debugged n verified in Ctx object attachment field is missing.

          Can u recollect did u modify anything in CSR for attachment. Can u plz confirm whether in ur env attachment is working

          Your quick response is really appreciated

          • José Quinto Zamora on June 15, 2015 at 5:17 pm said:

            Hi,
            Yes, the code is sent you is working in SharePoint 2013.
            Please, could you share more information about the error, Console Log in Developer Tools, your SharePOint version?

            Regards!

  4. raghu on June 8, 2015 at 7:53 am said:

    Hi,

    Thanks a lot for your replies, I tried your case by trying those 2 steps (register clienttemplates.js and NewForm) but it didn’t work. Tried in different Azure env also it didn’t.

    In this case also, when i debugged n verified in Ctx object attachment field is missing.

    Can u recollect did u modify anything in CSR for attachment. Can u plz confirm whether in ur env attachment is working

    Your quick response is really appreciated

    • José Quinto Zamora on June 15, 2015 at 5:20 pm said:

      Hi,

      Do you have attachments enabled in you SharePoint list? Be sure you are using SharePOint list now library and you are modifying JSLink in the WebPArt located on NewFOrm.aspx instead on AllItems.aspx.

      Regards!

  5. Hi Jose,

    I am also facing the same issue what Raghu facing. Can you please help in this regard? Thanks!

    • José Quinto Zamora on April 1, 2016 at 12:00 pm said:

      Hi Maruthu,
      Could you provide some Console log information about the specific error?

      F12 -> Console log you should find some information about what is happening.

      Regards!

  6. Jose,

    Great article!!!

    Just curious if you ever tried implementing this in Edit Form?

    • José Quinto Zamora on April 1, 2016 at 11:57 am said:

      Hi Arut,
      Not tested with Edit Form. But it shouldn’t be much different. Let me know if you try it and works!

      Regards!

  7. Pingback: How to implement Validation to require Attachments in a SharePoint List Item creation in SharePoint 2013 using Client-side Rendering – José Quinto | Soyka's Blog

Leave a Reply

Your email address will not be published.

Time limit is exhausted. Please reload CAPTCHA.

Post Navigation