Tuesday, September 30, 2014

Client Side Rendering using JSLink – Post 03 – Properties to override

Introduction

Read my first two post in order to get basics idea on Client Side rendering using JSLink.

In last two post we discussed basics on JSLink. Now lets look bit deeper. In this post I will illustrate; what are the fields we can override and use in template. I will give you examples for each and every property. Below are the properties that we can use to override in our custom template.

  • Header
  • Footer
  • View
  • Body
  • Group
  • Item
  • Fields
  • OnPreRender
  • OnPostRender

I have created an announcement list instance in order to illustrate the examples. My list instance displays as follows. Please note that I have grouped the list items by Created.

image

I have linked my JavaScript file for the above list instance. Now lets get into the examples.

Header

Overrides the Header of the list instance. The header area is described by the below image.

image

Code
  1. (function () {
  2.     // Initialize the variable that stores the objects.
  3.     var overrideCtx = {};
  4.     overrideCtx.Templates = {};
  5.  
  6.     // Change the header
  7.     overrideCtx.Templates.Header = "<b>This is a custom header</b>";
  8.  
  9.     // Register the template overrides.
  10.     SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
  11. })();

Results

image

Footer

We can add a footer in the list instance.

image

Code
  1. (function () {
  2.     // Initialize the variable that stores the objects.
  3.     var overrideCtx = {};
  4.     overrideCtx.Templates = {};
  5.  
  6.     // Change the footer
  7.     overrideCtx.Templates.Footer = "<b>This is a custom footer</b>";
  8.  
  9.     // Register the template overrides.
  10.     SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
  11. })();
Results

image

Fields

Visit my first blog post and see the example. You can understand how to override the fields. If you want to retrieve the actual value of a field you can retrieve by  “<#= ctx.CurrentItem.FieldName#>” or by ctx.CurrentItem.FieldName.

Code
  1. (function () {
  2.     // Initialize the variable that stores the objects.
  3.     var overrideCtx = {};
  4.     overrideCtx.Templates = {};
  5.  
  6.     overrideCtx.Templates.Fields = {
  7.         'Body': { 'View': '<div style="color:red; background-color: green"><#= ctx.CurrentItem.Body #></div>' }
  8.     };
  9.  
  10.     // Register the template overrides.
  11.     SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
  12. })();
Results

image

Group

Overriding Group takes 7 parameters. Using those parameters you can change the look and feel of the group. I will just show you a basic.

Code
  1. (function () {
  2.     // Initialize the variable that stores the objects.
  3.     var overrideCtx = {};
  4.     overrideCtx.Templates = {};
  5.  
  6.     overrideCtx.Templates.Group = customGroup;
  7.     // Register the template overrides.
  8.     SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
  9. })();
  10.  
  11. function customGroup(ctx, group, groupId, listItem, listSchema, level, expand) {
  12.     var html = '<div style="color:red">' + listItem[group] + ' </div>';
  13.     return html;
  14. }
Results

image

Body

Overrides the body.

Code
  1. (function () {
  2.     // Initialize the variable that stores the objects.
  3.     var overrideCtx = {};
  4.     overrideCtx.Templates = {};
  5.  
  6.     overrideCtx.Templates.Body = customBody;
  7.     // Register the template overrides.
  8.     SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
  9. })();
  10.  
  11. function customBody(ctx) {
  12.  
  13.     return String.format("Hello world from {0}", ctx.ListTitle);
  14.  
  15. }
Results

image 

Item

The Item template points to the function that displays each Item in the list.

Code

  1. (function () {
  2.     // Initialize the variable that stores the objects.
  3.     var overrideCtx = {};
  4.     overrideCtx.Templates = {};
  5.    
  6.     overrideCtx.Templates.Header = "<B><#=ctx.ListTitle#></B>" +
  7.         "<ul>";
  8.  
  9.     // This template is assigned to the CustomItem function.
  10.     overrideCtx.Templates.Item = customItem;
  11.     overrideCtx.Templates.Footer = "</ul>";
  12.  
  13.  
  14.  
  15.     // Register the template overrides.
  16.     SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
  17. })();
  18.  
  19. // This function builds the output for the item template.
  20. // It uses the context object to access announcement data.
  21. function customItem(ctx) {
  22.     // Build a listitem entry for every announcement in the list.
  23.     var ret = "<li>" + ctx.CurrentItem.Title + "</li>";
  24.     return ret;
  25. }

Results

image

OnPreRender

OnPreRender event fires before the DOM is loaded. In my example I will show how to set a custom list name.

Code
  1. (function () {
  2.     // Initialize the variable that stores the objects.
  3.     var overrideCtx = {};
  4.     overrideCtx.Templates = {};
  5.  
  6.     //Over ride the header
  7.     overrideCtx.Templates.Header = "<#=ctx.ListTitle#>";
  8.  
  9.     //Set the List title on pre render event
  10.     overrideCtx.OnPreRender = function a() {
  11.         ctx.ListTitle = "Title from PreRender";
  12.     };
  13.  
  14.     // Register the template overrides.
  15.     SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
  16. })();
Results

image 

OnPostRender

OnPostRender event fires after DOM is loaded. So you can change the values after DOM load. Here in our example I have changed the background color.

Code
  1. (function () {
  2.     // Initialize the variable that stores the objects.
  3.     var overrideCtx = {};
  4.     overrideCtx.Templates = {};
  5.     //OnPostRender call postRenderHandler function.
  6.     overrideCtx.OnPostRender = postRenderHandler;
  7.  
  8.     // Register the template overrides.
  9.     SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
  10. })();
  11. function postRenderHandler(ctx) {
  12.     var rows = ctx.ListData.Row;
  13.     for (var i = 0; i < rows.length; i++) {
  14.         var isApproved = rows[i]["Title"] == "Title 001";
  15.         if (isApproved) {
  16.             var rowElementId = GenerateIIDForListItem(ctx, rows[i]);
  17.             var tr = document.getElementById(rowElementId);
  18.             tr.style.backgroundColor = "#ada";
  19.         }
  20.     }
  21. }
Results

image `

Conclusion

So the basics are covered and if you are familiar with JavaScript and CSOM you can do more on Client side rendering with JSLink.  In future posts I will show some examples how you can use client side rendering.

Thursday, September 11, 2014

Client Side Rendering using JSLink – Post 02 – Customize List Forms

Introduction

In my last post I described how to startup with Client Side Rendering using JSLink with basic example. In this post I will describe “What are the places you can deploy JavaScript files in order to use in SharePoint development” and “How can we use rendering; in order to customize list forms”.

What are the places you can deploy JavaScript files in order to use in SharePoint development?

In my last post I had used layouts folder which is inside the 15 hive. But there are more options where we can deploy JavaScript files in order to use them in JSLink property. So these option can be useful for the developers who want to develop SharePoint hosted apps and who don’t have the access to local file system. JSLink property accepts below SharePoint tokens.

~site – The URL of the current website. (Recommended to use in SharePoint hosted apps development)

~sitecollection – The URL of the parent site collection of the current website.

~layouts – The URL of the Layouts virtual folder for the current website. You don’t have to worry about 14 hive or 15 hive.

~sitecollectionlayouts – The URL of Layouts folder in the current site collection (/sites/spsite/_layouts/15)

~sitelayouts – The URL of Layouts folder in the current site (/spsite/spweb/_layouts/15)

If you want to use multiple JavaScript file on a single JSLink property you can use “|” symbol.

Eg. ~layouts/folder001/test.js | ~layouts/folder002/test.js

How can we use rendering in order to customize list forms?

In the first post I described how to customize the default view form. In this post I will describe how to customize New form, Edit form and the Display form by changing the scope in JavaScript. I will show how to customize the New form and you can use the same for other forms as well.

Solution

  1. (function () {
  2.  
  3.     //   Initialize the variables for overrides objects
  4.     var overrideCtx = {};
  5.     overrideCtx.Templates = {};
  6.     overrideCtx.BaseViewID = "NewForm";
  7.     overrideCtx.ListTemplateType = "10000";
  8.  
  9.     /*
  10.    * Using the Fields override leaves the rest of the rendering intact, but
  11.    * allows control over one or more specific fields in the existing view
  12.    */
  13.     overrideCtx.Templates.Fields = {
  14.         'Title': { 'NewForm': 'Custom' }
  15.     };
  16.  
  17.     /*  
  18.      * Register the template overrides.
  19.      */
  20.     SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
  21.  
  22. })();

In the above code

BaseViewID: The form type. This can be NewForm, EditForm, DisplayForm.

ListTemplateType: This is List Template type. You can see your list template type in Elements.xml file belonging to the list definition in Visual Studio.

image image

The above JavaScript code shows how to modify the title value in the form.

Now you can save the JavaScript file in any locations as said under first heading.

We have one more thing to do. Reference the JavaScript file with the list for new form. 

Method 01 – Declaratively

I will show how to define JSLink in SPList Schema.xml file.

  1. Open the schema of List definition in your visual studio solution
  2. There at the bottom you can find the types of form.

image

3. Add a new property as JSLink and  give the location as mentioned below.

image

Now deploy the solution.

Method 02 – Programmatically in C#

Now I will show how to add JSLink property to NewForm programmatically through C#.

  1. SPWeb spWeb = SPContext.Current.Web;
  2.             SPList spList = spWeb.Lists.TryGetList("List Name");
  3.             SPForm newForm = spList.Forms[PAGETYPE.PAGE_NEWFORM];
  4.             SPFile page = spWeb.GetFile(newForm.Url);
  5.             using (SPLimitedWebPartManager wpManager = page.GetLimitedWebPartManager(PersonalizationScope.Shared))
  6.             {
  7.                 // Enable Update
  8.                 wpManager.Web.AllowUnsafeUpdates = true;
  9.  
  10.                 //Check out the file
  11.                 SPFile file = wpManager.Web.GetFile(newForm.Url);
  12.                 if (file.CheckOutType == SPFile.SPCheckOutType.None)
  13.                     file.CheckOut();
  14.  
  15.  
  16.                 foreach (WebPart webpart in wpManager.WebParts)
  17.                 {
  18.                     if (webpart is ListFormWebPart)
  19.                     {
  20.                         var listFormWebPart = (ListFormWebPart)webpart.WebBrowsableObject;
  21.                         listFormWebPart.TemplateName = "ListForm";
  22.                         listFormWebPart.JSLink = "/_layouts/15/CSR002/test.js";
  23.                         wpManager.SaveChanges(listFormWebPart);
  24.                     }
  25.                 }
  26.  
  27.                 // Update  file
  28.                 file.Update();
  29.                 file.CheckIn("Added JSLink");
  30.                 wpManager.Web.AllowUnsafeUpdates = false;
  31.             }

Actually what we are doing is – we are setting the value to JSLink property in web part on NewForm.aspx page.

The code below will NOT WORK.

  1. SPWeb spWeb = SPContext.Current.Web;
  2.             SPList spList = spWeb.Lists.TryGetList("CustomList002");
  3.             SPForm newForm = spList.Forms[PAGETYPE.PAGE_NEWFORM];
  4.             if (null != newForm)
  5.             {
  6.                 newForm.JSLink = "/_layouts/15/CSR002/test.js";
  7.             }
  8.             spWeb.AllowUnsafeUpdates = true;
  9.             spList.Update();
  10.             spWeb.AllowUnsafeUpdates = false;

Method 03 – Browser user interface

Go to the NewForm.aspx page where we try to add new item by clicking add new item button. Please refer my first post where I have described how to set JSLink property.

Conclusion

Once we deploy and give reference to our JavaScript file we can see that our Title value is changed to the customized value.

image

Keep in touch. I will cover more advanced topics on this.

Wednesday, September 3, 2014

Create Discussion Board list definition through Visual Studio 2012 for SharePoint 2013

Introduction

There was a requirement to create a discussion board list definition through visual studio. So that our client can be able to create list instance with some customization.

Problem Background

We tried to create content type by inheriting Discussion and then created a custom list definition using created content type. But it was not same as the out of the box discussion board – We couldn’t get the reply page and the views as in the ootb.

Solution

  • Create a new SharePoint solution
  • Add a content type inheriting from Discussion
    • Right Click on the project –> Add –> New Item –> Content Type –> Name it (I have named it as DisBoardCT) –> Click Add –> Select Discussion from Content type setting page

image

  • Create a List
    • Right Click on the project –> Add –> New Item –> List –> Click Add select the first option from Choose List Setting Page

image

  • Add the above created content type to our list

image

image

Now you list definition is ready. But this will not work as the out of the box discussion board.

  • Now you have to change the schema.xml
    • Go to the OOTB list definition usually the location is C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\TEMPLATE\FEATURES\DiscussionsList\Discuss
    • Copy the content in schema.xml and paste on our schema.xml in the visual studio
    • Get the Content type ID which we created.

    image

    • Replace the content type ID in schema.xml with our ID. There will be couple instances of the default content type. “0x012002”image
    • Once you change the content type in schema.xml the default content type in will be set to our custom content type. Please verify

image

  • Change the Type
    • Change the Type to 108 and the Image to

      Image="/_layouts/15/images/itdisc.png?rev=23"/>

      image

  • Change the Template type to 108 in list instance elements file.

image

image

  • Now deploy the solution and you should be able to get see the our custom discussion board list definition.

Conclusion

I have created a sample and you may download it here.

https://drive.google.com/file/d/0ByEnOE8DAdvhWUJ4ektWR2RBQXc/view?usp=sharing

Monday, September 1, 2014

Client Side Rendering using JSLink – Post 01 – Starting Over

Introduction

In SharePoint 2010, we use XSLT in order to customize the style of search results and view of list and list items. In SharePoint 2013 and for SharePoint Online it is recommended to use Client side rendering. Obliviously CSR is through JavaScript (of course; including CSS and HTML as well). Again, if you are familiar with XSLT you can still use it in SharePoint 2013 but note that XSLT falls under server side rendering.

Client Side rendering can be done via two methods.

Display Template: Used to style search results.
JS Link: Used to style the view of list, list items, fields, content type, List default pages (NewForm.aspx, EditForm.aspx, DispForm.aspx, AllItems.aspx ), List view web parts.

image

In this post I will just describe how to override a column field with our custom value and in future I will go in details with styling and all.

 

Advantages of Client Side rendering over using XSLT

  • Avoid unnecessary loads on server: JavaScript, HTML and CSS render on client browser and they avoid unnecessary loads on the server.
  • Easy to Debug: We use JavaScript for client side render. Modern browser supports debugging facility which XSLT is not providing.
  • More Libraries: We can use other JavaScript libraries as we needed (such as JQuery)
  • Easy to learn: SharePoint developers are becoming comfortable with JavaScript because of the trend of SharePoint hosted apps. So most developers are comfortable with JavaScript and feel easier to learn JavaScript than XSLT.
  • Flexibility: We can override particular fields, header, footer or the entire view of the list as we needed.

Disadvantages

  • Depends on client browser: If a user use old version of browser it may take long time to process the view; and if the user has disabled JavaScript or blocked JavaScript the rendering will not work. In case we use XSLT will work.
  • SEO Problem: Crawlers may not be able to understand the content generated by JavaScript.

Now lets cover some basic topics which we need

How to add JSLink to a List

Solution 01 – Through the browser user interface

  1. Go to the List.
  2. Click on edit page

    image

  3. Click on Edit Web Part
  4. At the bottom of the web part properties control there is a category called “Miscellaneous”. Expand it. At the bottom you can find a text box to add JS Link and there you can define the url for JS Link.

001

Solution 02 – Through Visual Studio

If you are trying to add a SharePoint list through visual studio declaratively this will be useful.

  1. Click on the schema.xml of your list

    image 

  2. Search for JSLink and you will see something like this. image

  3. Now you can give your own path of the JavaScript file. image

Basic Example

Now let’s create a basic JavaScript which overrides the value of our Body column of a announcement list.

Steps:

  1. Create an announcement list.
  2. Change the default view which displays the Body.
    • Modify view –> Select Body under the column name and click OK.image
  3. Now create a JavaScript file in side layouts folder inside 15 hive.
    • Usually the path will be C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\TEMPLATE\LAYOUTS\
    • In my case I created the JavaScript file as cutombody.js
  4. Now copy and paste the below code
  1. (function () {
  2.  
  3.     //   Initialize the variables for overrides objects
  4.     var overrideCtx = {};
  5.     overrideCtx.Templates = {};
  6.  
  7.     /*
  8.      * Using the Fields override leaves the rest of the rendering intact, but
  9.      * allows control over one or more specific fields in the existing view
  10.      */
  11.     overrideCtx.Templates.Fields = {
  12.         'Body': { 'View': 'Our Custom Value' }
  13.     };
  14.  
  15.     /*
  16.      * Register the template overrides.
  17.      */
  18.     SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideCtx);
  19. })();

In the above code overrideCtx variables holds current context of the list item. overrideCtx.Templates.Fields enables to access the individual list field. SPClientTemplates.TemplateManager.RegisterTemplateOverrides function registers our customized template; so that our list can use it.

Here we are overriding the Body (the internal name of the field) with the value “Our Custom Value”. Here the view is the scope. The scope can be DisplayForm, View, EditForm, NewForm.

Now save the JavaScript and give the JSLink as I have mentioned above under Solution 01. Your url will can be something like this. /_layouts/15/cutombody.js

Now our Announcement list will only display “Our Custom Value” in body field.

image

Conclusion

Stay Calm I will update more post with different examples with the code in upcoming days.

I have attached a Visual Studio solution file with a custom announcement list and have added the the list to XsltListViewWebPart and define the JSLink for the web part as well as for the list through the schema.xml. Please download it and make use of it.

https://drive.google.com/file/d/0ByEnOE8DAdvhcnRkWFBsR3ByYjQ/edit?usp=sharing

Reference

http://msdn.microsoft.com/en-gb/library/jj220045.aspx