SharePoint 2013 - Client Side Rendering

1. Client side rendering 代码结构为:

(function () {
    // Create object that have the context information about the field that we want to change it's output render 
    var linkFilenameFiledContext = {};
    linkFilenameFiledContext.Templates = {};
    linkFilenameFiledContext.Templates.Fields = {
        // Apply the new rendering for LinkFilename field on list view
        "LinkFilename": { "View": linkFilenameFiledTemplate }
    };
    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(linkFilenameFiledContext);
})();

2. Client Side Rendering 可以用来注册一个对象,这个对象用于去进行模板覆盖,对象包含以下几种属性:

View
Header
Body
Footer
Group
Item
Fields
OnPreRender
OnPostRende

3. Fields属性的格式为:overrideCtx.Templates.Fields = {FieldName : {Scope : Override}}, 使用ctx.CurrentFieldSchema.Name 来获取field的内部名称,例如:var priorityValue = ctx.CurrentItem[ctx.CurrentFieldSchema.Name]

FieldName - This is the internal name of the field you want to override.
Scope – This defines when to override the field. The choices are “View”,”DisplayForm”,”EditForm”, and “NewForm”.
Override – The actual override. This can be a HTML string with JavaScript embedded, or a function to be executed. In the former, it should be in the format: “<p> <#= ctx.CurrentItem.PercentComplete #></p>”, where “<p>” is just some HTML, and everything enclosed in “<#= #>” is JavaScript to be executed.

4. 使用clientform.js, clientpeoplepicker.js, 和autofill.js文件来生成client people picker:

页面代码:

<SharePoint:ScriptLink name="clientforms.js" runat="server" LoadAfterUI="true" Localizable="false" />
    <SharePoint:ScriptLink name="clientpeoplepicker.js" runat="server" LoadAfterUI="true" Localizable="false" />
    <SharePoint:ScriptLink name="autofill.js" runat="server" LoadAfterUI="true" Localizable="false" />
<div id="peoplePickerDiv"></div>

JS代码:

function initializePeoplePicker(peoplePickerElementId) {

    // Create a schema to store picker properties, and set the properties.
    var schema = {};
    schema['PrincipalAccountType'] = 'User,DL,SecGroup,SPGroup';
    schema['SearchPrincipalSource'] = 15;
    schema['ResolvePrincipalSource'] = 15;
    schema['AllowMultipleValues'] = true;
    schema['MaximumEntitySuggestions'] = 50;
    schema['Width'] = '280px';

    // Render and initialize the picker. 
    // Pass the ID of the DOM element that contains the picker, an array of initial
    // PickerEntity objects to set the picker value, and a schema that defines
    // picker properties.
    this.SPClientPeoplePicker_InitStandaloneControlWrapper(peoplePickerElementId, null, schema);

5. 修改View或者Field的显示方式时,需要使用clienttemplate.js文件,参考示例

具体操作为:先创建一个对象来存储要更改对象的上下文信息,然后使用SPClientTemplates.TemplateManager.RegisterTemplateOverrides()来注册这个对象进行覆盖;

修改View显示方式的JS代码:

(function () {

    // Initialize the variable that store the objects.
    var overrideCtx = {};
    overrideCtx.Templates = {};


    // Assign functions or plain html strings to the templateset objects:
    // header, footer and item.
    overrideCtx.Templates.Header = "<B><#=ctx.ListTitle#></B>" +
        "<hr><ul id='unorderedlist'>";

    // This template is assigned to the CustomItem function.
    overrideCtx.Templates.Item = customItem;
    overrideCtx.Templates.Footer = "</ul>";

    // Set the template to the:
    //  Custom list definition ID
    //  Base view ID
    overrideCtx.BaseViewID = 2;
    overrideCtx.ListTemplateType = 10057;

    // Assign a function to handle the
    // PreRender and PostRender events
    overrideCtx.OnPreRender = preRenderHandler;
    overrideCtx.OnPostRender = postRenderHandler;

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

// This function builds the output for the item template,
// it uses the context object to access announcement data.
function customItem(ctx) {

    // Build a listitem entry for every announcement in the list.
    var ret = "<li>" + ctx.CurrentItem.Title + "</li>";
    return ret;
}

// The preRenderHandler handles the 
// OnPreRender event
function preRenderHandler(ctx) {

    // Override the default title with user input
    ctx.ListTitle = prompt("Type a title", ctx.ListTitle);
}

// The postRenderHandler handles the 
// OnPostRender event
function postRenderHandler(ctx) {

    // You can manipulate the DOM
    // in the postRender event
    var ulObj;
    var i, j;

    ulObj = document.getElementById("unorderedlist");
    
    // Reverse order the list
    for (i = 1; i < ulObj.children.length; i++) {
        var x = ulObj.children[i];
        for (j = 1; j < ulObj.children.length; j++) {
            var y = ulObj.children[j];
            if(x.innerText<y.innerText){                  
                ulObj.insertBefore(y, x);
            }
        }
    }
}

 修改Field显示方式的JS代码(可以为Field提供View, DisplayForm, EditForm, NewForm的显示模板):

// List View – Priority Color Sample
// Muawiyah Shannak , @MuShannak

(function () {

    // Create object that have the context information about the field that we want to change it's output render 
    var priorityFiledContext = {};
    priorityFiledContext.Templates = {};
    priorityFiledContext.Templates.Fields = {
        // Apply the new rendering for Priority field on List View
        "Priority": { "View": priorityFiledTemplate }
    };

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(priorityFiledContext);

})();

// This function provides the rendering logic for list view
function priorityFiledTemplate(ctx) {

    var priority = ctx.CurrentItem[ctx.CurrentFieldSchema.Name];

    // Return html element with appropriate color based on priority value
    switch (priority) {
        case "(1) High":
            return "<span style='color :#f00'>" + priority + "</span>";
            break;
        case "(2) Normal":
            return "<span style='color :#ff6a00'>" + priority + "</span>";
            break;
        case "(3) Low":
            return "<span style='color :#cab023'>" + priority + "</span>";
    }
}

为Field提交时注册事件的JS代码:

(function () {

    // Create object that have the context information about the field that we want to change it's output render 
    var ageFiledContext = {};
    ageFiledContext.Templates = {};
    ageFiledContext.Templates.Fields = {
        // Apply the new rendering for Age field on New and Edit forms
        "Age": {
            "NewForm": ageFiledTemplate,
            "EditForm": ageFiledTemplate
        }
    };

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(ageFiledContext);

})();


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

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

    // Register a callback just before submit.
    formCtx.registerGetValueCallback(formCtx.fieldName, function () {
        return document.getElementById('inpAge').value;
    });

    // Render Html5 input (number)
    return "<input type='number' id='inpAge' min='0' max='110' value='" + formCtx.fieldValue + "'/>";
}

 

6. 在除浏览器地址栏之外的其它地方,尽量不要使用%20替代空格,否则,在非IE浏览器(例如Chrome)中不能够识别,比如:

此处如果使用%20,则在Chrome中不能工作; 

 

而且不能使用绝对路径或者相对路径,要使用token符号来替代web路径,详情参考此页面

JSLink URLs and Tokens
When you are constructing your JSLink URL there are a number of tokens you can take advantage of:

~site – reference to the current SharePoint site (or “Web”)
~sitecollection – reference to the current SharePoint site collection (or “Site”)
~layouts – version specific reference to the web application Layouts folder (so it will automatically swap out /_layouts/14 or /_layouts/15 for you)
~sitecollectionlayouts – reference to the layouts folder in the current site collection (e.g. /sites/team/_layouts/15)
~sitelayouts – reference to the layouts folder in the current site (e.g. /sites/teams/subsite/_layouts/15)

 

 7. 为Field添加验证时需要用到 SPClientForms.ClientValidation 对象

   var validators = new SPClientForms.ClientValidation.ValidatorSet();
    validators.RegisterValidator(new emailValidator());

    // Validation failure handler.
    formCtx.registerValidationErrorCallback(formCtx.fieldName, emailOnError);

    formCtx.registerClientValidator(formCtx.fieldName, validators);


// Custom validation object to validate email format
emailValidator = function () {
    emailValidator.prototype.Validate = function (value) {
        var isError = false;
        var errorMessage = "";

        //Email format Regex expression
        var emailRejex = /\S+@\S+\.\S+/;
        
        if (!emailRejex.test(value) && value.trim()) {
            isError = true;
            errorMessage = "Invalid email address";
        }

        //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 emailOnError(error) {
    document.getElementById("spnError").innerHTML = "<span role='alert'>" + error.errorMessage + "</span>";
}

8. 设置Field为只读时,可以使用SharePoint已有的javascript方法:

// List add and edit – ReadOnly SP Controls Sample

(function () {

    // Create object that have the context information about the field that we want to change it's output render 
    var readonlyFiledContext = {};
    readonlyFiledContext.Templates = {};
    readonlyFiledContext.Templates.Fields = {
        // Apply the new rendering for Age field on Edit forms
        "Title": {
            "EditForm": readonlyFieldTemplate
        }
    };

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(readonlyFiledContext);

})();

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

    //Reuse ready sharepoint javascript libraries
    switch (ctx.CurrentFieldSchema.FieldType) {
        case "Text":
        case "Number":
        case "Integer":
        case "Currency":
        case "Choice":
        case "Computed":
            return SPField_FormDisplay_Default(ctx);

        case "MultiChoice":
            prepareMultiChoiceFieldValue(ctx);
            return SPField_FormDisplay_Default(ctx);

        case "Boolean":
            return SPField_FormDisplay_DefaultNoEncode(ctx);

        case "Note":
            prepareNoteFieldValue(ctx);
            return SPFieldNote_Display(ctx);

        case "File":
            return SPFieldFile_Display(ctx);

        case "Lookup":
        case "LookupMulti":
                return SPFieldLookup_Display(ctx);           

        case "URL":
            return RenderFieldValueDefault(ctx);

        case "User":
            prepareUserFieldValue(ctx);
            return SPFieldUser_Display(ctx);

        case "UserMulti":
            prepareUserFieldValue(ctx);
            return SPFieldUserMulti_Display(ctx);

        case "DateTime":
            return SPFieldDateTime_Display(ctx);

        case "Attachments":
            return SPFieldAttachments_Default(ctx);

        case "TaxonomyFieldType":
            //Re-use ready sharepoint inside sp.ui.taxonomy.js javascript libraries
            return SP.UI.Taxonomy.TaxonomyFieldTemplate.renderDisplayControl(ctx);
    }
}

//User control need specific formatted value to render content correctly
function prepareUserFieldValue(ctx) {
    var item = ctx['CurrentItem'];
    var userField = item[ctx.CurrentFieldSchema.Name];
    var fieldValue = "";

    for (var i = 0; i < userField.length; i++) {
        fieldValue += userField[i].EntityData.SPUserID + SPClientTemplates.Utility.UserLookupDelimitString + userField[i].DisplayText;

        if ((i + 1) != userField.length) {
            fieldValue += SPClientTemplates.Utility.UserLookupDelimitString
        }
    }

    ctx["CurrentFieldValue"] = fieldValue;
}

//Choice control need specific formatted value to render content correctly
function prepareMultiChoiceFieldValue(ctx) {

    if (ctx["CurrentFieldValue"]) {
        var fieldValue = ctx["CurrentFieldValue"];

        var find = ';#';
        var regExpObj = new RegExp(find, 'g');

        fieldValue = fieldValue.replace(regExpObj, '; ');
        fieldValue = fieldValue.replace(/^; /g, '');
        fieldValue = fieldValue.replace(/; $/g, '');

        ctx["CurrentFieldValue"] = fieldValue;
    }
}

//Note control need specific formatted value to render content correctly
function prepareNoteFieldValue(ctx) {

    if (ctx["CurrentFieldValue"]) {
        var fieldValue = ctx["CurrentFieldValue"];
        fieldValue = "<div>" + fieldValue.replace(/\n/g, '<br />'); + "</div>";

        ctx["CurrentFieldValue"] = fieldValue;
    }
}

 8. 隐藏Field时,可以在OnPostRender事件使用jQuery方法

(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('<script src="//ajax.aspnetcdn.com/ajax/jquery/jquery-1.10.0.min.js"><\/script>'));

    // Create object that have the context information about the field that we want to change it's output render 
    var hiddenFiledContext = {};
    hiddenFiledContext.Templates = {}; 
    hiddenFiledContext.Templates.OnPostRender = hiddenFiledOnPreRender;
    hiddenFiledContext.Templates.Fields = {
        // Apply the new rendering for Age field on New and Edit forms
        "Predecessors": {
            "NewForm": hiddenFiledTemplate,
            "EditForm": hiddenFiledTemplate
        }
    };

    SPClientTemplates.TemplateManager.RegisterTemplateOverrides(hiddenFiledContext);

})();


// This function provides the rendering logic
function hiddenFiledTemplate() {
    return "<span class='csrHiddenField'></span>";
}

// This function provides the rendering logic
function hiddenFiledOnPreRender(ctx) {
    jQuery(".csrHiddenField").closest("tr").hide();
}

 9. 使用sp.ui.controls.js文件来定义client chrome control,需要使用jQuery或MicrosoftAjax.js来支持:

// Prepare the options and render the control
// The Help, Account and Contact pages receive the 
//   same query string parameters as the main page
var options = {
    "appIconUrl": "../Images/AppIcon.png",
    "appTitle": "Basic tasks using the JSOM",
    "appHelpPageUrl": "Help.html?"
        + document.URL.split("?")[1],
    "settingsLinks": [
        {
            "linkUrl": "Account.html?"
                + document.URL.split("?")[1],
            "displayName": "Account settings"
        },
        {
            "linkUrl": "Contact.html?"
                + document.URL.split("?")[1],
            "displayName": "Contact us"
        }
    ]
};

var nav = new SP.UI.Controls.Navigation(
                        "chrome_ctrl_placeholder",
                        options
                    );
nav.setVisible(true);

效果为:

 

10. mapviewtemplate.js用来设置一个含有geolocation类型字段的视图,效果如下:

11. 

 

posted @ 2014-07-31 10:33  Jacky Ge  阅读(1825)  评论(0编辑  收藏  举报