Changing Site Contents from a Grid to a List

This is something that has been bugging me for a while, and something that has clearly been bugging my users (as they keep saying they can never find anything).

The problem with the tile view is that you have to scan both left-right as well as up-down to find the item you are looking for. With a large number of lists this quickly becomes extremely painful to find what you are looking for.

The standard “Site Contents” view .. in all its nasty tile-layout glory

So I thought, how could you turn it back?

Well, the good news is that the Site Contents view is actually all formatted using CSS with unique IDs and classes, which makes it a snip. the sample I’ve done below is in jQuery (because it is easy to pin a JavaScript file to every page and it works with Office 365 just as well).

So first off we need ourselves a function to reset all of the

function HideTiles() {
  $(“#applist .ms-vl-apptile”).css({ “display”: “block” });
  $(“#applist .ms-vl-apptile”).css({ “min-height”: “50px” });
   $(“#applist .ms-vl-appinfo”).css({ “min-height”: “50px” });
  $(“#applist .ms-vl-appinfo”).css({ “width”: “500px” });
  $(“#applist .ms-vl-appimage”).css({ “height”: “50px” });
  $(“#applist .ms-vl-appimage”).css({ “width”: “50px” });

  $(“#applist #apptile-appadd .ms-vl-appimage”).css({ “width”: “96px” });

  $(“#applist .ms-vl-appimage a.ms-storefront-appiconspan”).css({ “height”: “50px” });
  $(“#applist .ms-vl-appimage a.ms-storefront-appiconspan”).css({ “width”: “50px” });
  $(“#applist .ms-vl-appimage a.ms-storefront-appiconspan”).css({ “line-height”: “50px” });

  $(“#applist img.ms-storefront-appiconimg”).css({ “height”: “50px” });
  $(“#applist img.ms-storefront-appiconimg”).css({ “line-height”: “50px” });
  };

Then we need to actually make sure this gets executed. The problem here is that the Site Contents is rendered on-the-fly using JavaScript so we have to resort to a little Script on Demand to get this working.  

$(function () {
  ExecuteOrDelayUntilScriptLoaded(HideTiles, “sp.ui.allapps.js”);
});

Then the only thing needed is to make sure this script gets dropped onto the page and I’ve done this using a Custom Action (I could have used a delegate control with CSS style tags but that doesn’t work in the Sandbox, i.e. Office 365)

<CustomAction
  ScriptSrc=~SiteCollection/_layouts/15/MJH.JSLink/MJH.AddCss.js
  Location=ScriptLink
  Sequence=20>
</CustomAction>

So if you set this up it looks something like this.



New formatting (in a single alphabetical list)

Now I admit, the formatting is pretty crude and it could do with a certain amount of smartening up, but the principle is sound and at least the owners of sites with large numbers of lists get an easier to navigate list which is alphabetical, instead of having to scan a page of dozens of tiles.

JSLink and Display Templates Part 5 – Creating custom List Views

This post will look at a slightly different scenario – List Views. The general principles are the same (we write some JavaScript which tells SharePoint to override the rendering of various elements) but because we are now dealing with a whole view instead of just a single field there are some new elements to play with.

This is actually one of the more simple examples so I’ll start with all of the JavaScript in one block

var mjhViews = mjhViews || {};

mjhViews.itemHtml = function (ctx) {
  var returnHtml = “<h2>” + ctx.CurrentItem.Title + “</h2>”;

  if (ctx.CurrentItem.MyCustomField) {
    returnHtml += “<p>” + ctx.CurrentItem.MyCustomField + “</p>”;
  } 
  return returnHtml;
};

(function () {
  var mjhOverrides = {};
  mjhOverrides.Templates = {};

  mjhOverrides.Templates.Header = “<div id=’MyCustomView’>”;
  mjhOverrides.Templates.Item = mjhViews.itemHtml;
  mjhOverrides.Templates.Footer = “</div>”;
 
  mjhOverrides.ListTemplateType = 104;
  mjhOverrides.BaseViewID = 1;
 
  SPClientTemplates.TemplateManager.RegisterTemplateOverrides(mjhOverrides);
})();


So we start off as good JavaScript developers and create ourselves a namespace (mjhViews) for our function (so we don’t pollute the global namespace). This contains a single function (mjhViews.itemHtml) which accepts the same render context object we’ve been using throughout this series.

The itemHtml method simply returns some basic HTML consisting of the item Title in an H2 element followed by the “MyCustomField” (if it exists, this field was used in Parts 3 and 4). Of course there are different methods for retrieving the values of the current item but the render context will automatically provide properties for the basic data types (some field types, external data fields in particular, don’t work like this and you might need to get creative with AJAX REST calls but be careful about performance!).

Finally we have our anonymous function which actually registers this override with SharePoint, and this is where things get interesting.

The main thing you might notice here is that we aren’t controlling any specific fields but instead override the “Header” and “Footer” with plain old HTML. For the “Item” we reference our rendering method and this will be executed for every item present in the view.

We then have two more properties (both of which are optional by the way).
The ListTemplateType and the BaseViewID both define which specific list types and views this rendering should be used for. If you don’t specify values for these then when this rendering override is registered it will override EVERY list and view on the page.

Finally we use the same old RegisterTemplateOverrides to tell SharePoint to process our object and do its thing!

Now before I apply this view it looks like this (which should be a pretty familiar SharePoint view):

Standard SharePoint list view

Once I apply my custom view rendering it looks like this:

A custom (if slightly boring) list view done with JavaScript

So .. quite easy huh? But the bright among you might have wondered .. where the hell has the toolbar and paging gone? Ahh .. yes .. that is all handled by the header and footer.

The header and footer contain important List View elements

This isn’t the only setback, if you try to use the view I defined above in “Quick Edit” mode then you also get the following error message:

TypeError: Unable to get property ‘style’ of undefined or null reference

The problem is that if you don’t override the Header you get some slightly funky behaviour because the headers injects a table object and it expects your content to be rendered inside that HTML table as rows. So by default I end up with the following (note the headers are at the bottom!)

Custom rendering with the header intact, but column headers are appearing AFTER the other content

So if you really want to play ball with the list views (and want the headers to be available) then you need to use TR and TD elements for your render HTML. For example:

mjhViews.itemHtml = function (ctx) {
  // start with a <tr> and a <td>
  var returnHtml = “<tr><td colspan=’3′>”;

  returnHtml += “<h2>” + ctx.CurrentItem.Title + “</h2>”;

  if (ctx.CurrentItem.MyCustomField) {
    returnHtml += “<p>” + ctx.CurrentItem.MyCustomField + “</p>”;
  }
  // close off our <td> and <tr> elements
  returnHtml += “</td></tr>”;
  return returnHtml;
};
Once we put this in place, our headers are back in the right place.

Custom rendering with column headers in the right place

Making your views use the correct Display Template
In order to make sure the Display Templates are used in the correct places you have a number of options.

  1. In your schema.xml of a custom list definition you can define the JSLink property allowing you to override specific views. This allows you to build List Templates which have completely bespoke views when required (especially useful for use with list view web parts)
  2. You can define the JSLink property on the List View Web Part .. and this works either for defined views in the List or for List View Web Parts which you have dropped onto other web part pages or publishing pages.
  3. You can use Code / PowerShell to modify the JSLink property of the SPView object programmatically
  4. You can of course just drop in your JavaScript file using a Script Editor or custom Master Page and use the ListTemplateType and BaseViewID properties I told you about at the beginning on this post 🙂
  5. or you can use a funky new method which allows users to create their own views using your custom templates … but more about that in Part 6 🙂

So that pretty much covers off how list views can be rendered using bespoke code. Hope you’ve been enjoying the series but we’re not done yet!

..

Next – Part 6 – Creating View Templates and Deployment Options

JSLink and Display Templates Part 4 – Validating user input

In the previous posts we have looked at JSLink and how we can use it, we have looked at overriding the rendering of individual fields both for display and also for editing. Now we are going to look at Validators and how we can validate user input before their changes are saved.

In order for a validator to work you need three moving parts:

  • Validation method (to tell SharePoint if the field input is valid or not)
  • OnError method (to handle any errors which are raised)
  • Registration code to do the plumbing

Validation Method
We’ll base this sample on the Custom Editing interface we built in Part 3 and first off we will build ourselves a validation method.

This is technically going to be an object with a Validate method (to which SharePoint will pass a value). The code for this method is as follows:

mjh.MyCustomFieldValidator = function () {
  mjh.MyCustomFieldValidator.prototype.Validate = function (value) {
    var isError = false;
    var errorMessage = “”;

    if (value == “Item 2”) {
      isError = true;
      errorMessage = “You cannot select ‘Item 2′”;
    }
    returnnew SPClientForms.ClientValidation.ValidationResult(isError, errorMessage);
  };
};

The code above contains a very simple if statement to check the items value (in my example saying that an error message will be displayed if the item value is set to “Item 2” .. one of the drop-down choices from Part 3 of this series).

Finally we call the SPClientForms.ClientValidation.ValidationResult method passing in our “isError” (a true/false boolean) and the error message (a text string).

OnError Method
We then need a final method which tells SharePoint basically what to do when an error actually occurs. This is a fairly simple method in which you can basically do whatever you want (pop-up alerts, add HTML to the page, change CSS, whatever you need).

Now we could just use an Alert(error.message) function if we wanted a particularly crude error message but it would be much better to have some formatted error message just like SharePoint does out of the box .. and for that to work we first need to have ourselves a recognisable element that we can manipulate using jQuery, so we add the following code to our rendering method for the edit interface:

// add the error span
returnHtml += “<span id=’MyCustomFieldError’ class=’ms-formvalidation ms-csrformvalidation’></span>”;

Once we have this we can manipulate it in our “onError” function (which as you can see is very simple).

mjh.onError = function (error) {
  $(“#MyCustomFieldError”)
  .html(“<span role=’alert’>” + error.errorMessage + “</span>”);
};

So all we are really doing is grabbing the span using the ID we gave it, then injecting our error message.

Now for the plumbing …
So the only thing missing is making this all hang together from inside our render method:
var formCtx = SPClientTemplates.Utility.GetFormContextForCurrentField(ctx);

// register the field validators

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

if (formCtx.fieldSchema.Required) {
  fieldValidators.RegisterValidator(
    new SPClientForms.ClientValidation.RequiredValidator()
  );
} fieldValidators.RegisterValidator(new mjh.MyCustomFieldValidator());

formCtx.registerValidationErrorCallback(formCtx.fieldName, mjh.onError);
formCtx.registerClientValidator(formCtx.fieldName, fieldValidators);

So lets walk through what we are doing in the code above.

First off we create ourselves a new ValidatorSet which will contain the validators that we need for the field. We then do a simple check to see if it is a required (mandatory) field and if it is we add the standard SharePoing “RequiredValidator” to our ValidatorSet.

Then we add our own new “MyCustomFieldValidator” object to the validator set.

Finally we have two register methods. The first one registerValidationErrorCallback is basically telling SharePoint that if our field fails validation that it should call the mjh.onError method to deal will letting the user know what has gone wrong.

The second one registerClientValidator actually registers our validators with SharePoint for the chosen field.

Note – it is perfectly possible to register your client validator without providing a validation error callback. If you do this then the validator will stop the form from being saved but the user won’t be told why (they’ll just get a frustrating form which won’t post back).

So ..  assuming all of the above has worked correctly you would see something like this if you tried to selected “Item 2”:

Validation message being shown in SharePoint

So that should be what you need to start putting together your own custom validation. You can of course use this technique on any number of fields.

For the complete code-sample to date (including Parts 2 and 3) please download the Visual Studio solution here:

https://sdrv.ms/15eB6CI

….

Next – Part 5 – Creating Custom List Views

JSLink and Display Templates Part 3 – Creating a custom editing interface

So this part talks about some of the more interesting bits of Display Templates .. the editing interface. This introduces some new features as not only are we required to provide and rendering all of the editing controls but we also have to somehow get SharePoint to understand what value it should use when someone wants to save their changes.

Now the process for creating an editing interface is identical for both “New” and “Edit” forms (with the exception that the editing interface also needs to deal with loading up existing values) so for this post our examples will focus on the “Edit Form” functionality.

Registering our Edit Form function
So this uses exactly the same technique that we walked through in Part 2, where we register our desired override method for our named field.

(function() {
  var mjhOverrides = {};
  mjhOverrides.Templates = {};

  mjhOverrides.Templates.Fields = {  

    ‘MyCustomField’: {
      ‘NewForm’: mjh.editMethod,
      ‘EditForm’: mjh.editMethod
    }
  };

  SPClientTemplates.TemplateManager.RegisterTemplateOverrides(mjhOverrides );
 })();
So just like before we create ourselves an override object and tell it we want to use the method “mjh.editMethod(ctx)” to render both the “EditForm” and “NewForm” for our field “MyCustomField” and we then register that using the SPClientTemplates.TemplateManager.RegisterTemplateOverrides method.

The Edit Render Method
The format of the rendering method for the edit interface (in this example) is pretty straightforward. I have simply rendered out a drop-down list containing three items.

mjh.editMethod = function (ctx) {
  var formCtx = SPClientTemplates.Utility.GetFormContextForCurrentField(ctx); 

  formCtx.registerGetValueCallback(formCtx.fieldName, mjh.getFieldValue.bind(null, formCtx.fieldName));

  // items to appear in the drop down list
  var items = new Array(“Item 1”, “Item 2”, “Item 3”);
  var returnHtml = “<div id=” + ctx.CurrentFieldSchema.Name + “><select>”;
 
  for (var i = 0; i < length; i++) {
    returnHtml += “<option”;
    if (ctx.CurrentFieldValue == items[i]) {
      // select the current item if the value matches
      returnHtml += ” selected “;
    }  
    returnHtml += “>” + items[i] + “</option>”;
  }

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

 

Now as you can see this time we have a new method in play as we are also creating a new “FormContext” object and using the registerGetValueCallback method. This method is what tells SharePoint to use our method to find out what the field value should be when the item is saved. The first argument is the name of the field we are overriding, and the second argument is the method that will return our field value.

We have also made use of the JavaScript “bind” function so that we can specify arguments that should be passed to our callback method, in this case we want to pass the field name (you’ll see why in a minute). 

The only other thing special going on here is that I check to see if the current value of the item matches the option, and if it is we add the “selected” attributed.

We have also enclosed the whole thing in a div using the fieldname as the ID, which we can use in our callback method below …

The Get Value callback
The next thing of course is our method to retrieve the actual field value, and for this we use a little bit of jQuery (you can choose your own way of getting the jQuery library onto the page. Adding it as an extra JSLink URL is quite cool, although if you use jQuery everywhere you might otherwise want to use a Custom Action or Delegate Control so it appears on every page).

mjh.getFieldValue = function (fieldName) {
  // a div used with jQuery to identify the appropriate items 
  var divId = “#” + fieldName;
  // get the selected item 
  var selectedItem = $(divId + ‘ option:selected’)[0];
  // return the value 
  return selectedItem.innerText;
};
So you can see above that we are using the fieldName argument so we can identify the correct div. This allows us to use the same methods on multiple fields without them clashing.
We then simply use a small jQuery statement to pull out the selected item (the “option” element which has an attributed of “selected”) and return the “innerText” (which in our example is the value we want to save). Of course you need to be mindful of the data type of the field you are working with. All values are returned as Text but fields such as People and Lookup Fields need to return a specifically formatted string.
I then bound this to a site column (of type Text) with the following schema:
<Field ID={A424AE9E-1F1D-4ECE-B695-202F5106352E}
  Name=MyCustomField
  DisplayName=My Custom Field
  Description=a text field which has custom rendering?
  Type=Text
  Required=FALSE
  Group=MJH JSLink Columns
  JSLink=~layouts/MJH.JSLink/jquery-1.10.2.min.js|~layouts/MJH.JSLink/MJH.JSLink.js
  Overwrite=TRUE>
</Field>
Once that is all deployed it should look something like this …

My Custom Field – a Text field but rendered as a drop-down list

So that is pretty much all you need to get going with editing of fields. Come back for Part 7 where I share sample code for handling Lookup Fields (and converting them to checkbox lists), cascading dropdowns and generating values by calling AJAX REST queries.

In the meantime you can download the sample code from this example here:
https://sdrv.ms/14KtFgv

Next – Part 4 – Validating user input

JSLink and Display Templates Part 2 – Changing how individual fields display

This is part two in my JSLink and Display Template series, and in this post we will be looking at the actual Display Template JavaScript code to override the rendering of individual fields.

If you haven’t read Part 1 and then it is well worth a look, if nothing else you need to understand the URL tokens and where/how you use JSLink to get your Display Template in the right place.

So what will we be doing?
The premise of using Display Templates here is simple, we are going to tell SharePoint
that when it wants to render a field we want it to use one of our JavaScript functions instead of the “out of the box” one.

We can do this on each field for four different rendering methods:

  • Display Forms
  • Edit Forms
  • New Forms
  • Views (as in, list views)

This post will look at the “Display Form” while the others are covered in further posts in this series.

Registering your Override Methods
The magic all happens through a SharePoint JavaScript method called SPClientTemplates.TemplateManager.RegisterTemplateOverrides(ctx). This expects a single object to be passed in which declares what exactly we want to override.

This method call is actually the same we use throughout this series, but in this example we will focus on the Fields part of it.

In order to do this we need to create an object which has an empty “Templates” object value. This “Templates” object then contains a “Fields” object value which contains an array specifying the fields we want to override. Each field override then refers to methods which contains the rendering logic for that field.

We finally pass our main object over to the RegisterTemplateOverrides method and let SharePoint take care of the rest. For example:

(function() {
  var mjhOverrides = {};
  mjhOverrides.Templates = {};

  mjhOverrides.Templates.Fields = { 

    ‘MyCustomField’: {
      ‘DisplayForm’: mjh.displayMethod
    }
  };

  SPClientTemplates.TemplateManager.RegisterTemplateOverrides(mjhOverrides );

})();

So in the example code above we create our override object called “mjhOverrides” (which has a “Templates.Fields” value).  We then assigned an array (of one item) which specified the InternalName of the field I want to override (in this case “MyCustomField”).

I then specified that when SharePoint wants to render this field for a “Display Form” then I want it to use my own method called “mjh.displayMethod”

The whole thing is wrapped in an anonymous self-executing function so that it executes as soon as the page is loaded but doesn’t pollute the global namespace.

Of course, you could specify multiple different fields or multiple different override methods, this uses simple JavaScript array principles and an example is shown below:

mjhOverrides.Templates.Fields =

{ 

  ‘MyCustomField: {
    ‘DisplayForm’: mjh.displayMethod,
    ‘View’: mjh.viewMethod
  }, 
  ‘Title’: {
    ‘DisplayForm’: mjh.displayMethod,
    ‘View’: mjh.viewTitleMethod
  }

};

So in the above example we are overriding two different fields (a custom field called “MyCustomField” and the out of the box “Title” field). For each field we specify overrides for both the DisplayForm and the View (List View) methods.

Note that we can re-use the same rendering method multiple times for different fields (so it is highly recommended to try and build reusable generic render methods where possible).

Format of a Render Method
So now that we have told SharePoint which render method we want it to use I suppose it would be useful to actually write it. Being a good JavaScript citizen we declared our own namespace for our functions so we didn’t pollute the global namespace, so the function starts off with a simple method declaration.

var mjh = mjh || {};

mjh.displayMethod = function (ctx) {
  return ‘<div>Hello World</div>’;
}

The format as you can see is very simple. All we need to do is return a string which contains the HTML we want to display. This example is not particularly useful as every item will render the same HTML (a simple Hello World message).

Hopefully you can appreciate that with the power of JavaScript and CSS you really do have full-reign to do whatever you want here. You can declare JavaScript events for AJAX REST calls or simply using some CSS and jQuery to create a funky dynamic interface (or just output some nice clean HTML).

However, this example isn’t terribly useful as what we REALLY want are access to the item values, and this is where the “ctx” object comes in. This is a method argument which SharePoint automatically provides and is a “Render Context” object.

Now I really haven’t been able to find very much information on MSDN / TechNet (read – actually I’ve found nothing) which describes this object and all of its methods, but from inspecting the JavaScript object using the developer tools I’ve managed to gleam a fair bit of detail. I’ve listed the basic values below, but to be honest you’d get a lot of value by poking around in the script debugger and checking out this object in more detail.

// value of the current field
var currentValue = ctx.CurrentFieldValue;

// the list item object
var item = ctx.CurrentItem;

// get the schema for the field
var field = ctx.CurrentFieldSchema;

So in order to make our display method a little more useful we should update it to the following:

mjh.displayMethod = function (ctx) {
  return ‘<div class=’mjhCustomField’>’ + ctx.CurrentFieldValue + ‘</div>’;
}

So now we have our item being displayed in a custom div with our own class. We can of course properly go to town on this but you get the idea 🙂

This is all then wrapped into a JavaScript file and attached either to the Site Column (declaratively in XML) or the List Form Web Part, or the Content Type (for more information on how to do that please go and read Part 1).

So that is about as complicated as it gets for Display Forms, but don’t worry, we have all sorts of fun and games coming up in the next parts in the series, first creating custom editing interfaces, providing validator methods and overriding views.

Next : Part 3 – Creating a custom editing interface

JSLink and Display Templates Part 1 – Overview, URL Tokens and Applying JSLink to objects

This is the first in a 4 part series about JSLink where I intend to go through all the ins and outs of using Display Templates to customise list rendering.

This first section really covers off the basics. It doesn’t contain any real sample code about the Display Templates (that is in Parts 2, 3 and 4) but does explain what JSLink is and how you can apply it to different objects.

What is “JSLink” exactly?
I think there has been a fair amount of confusion over what the terminology “JSLink” actually means. I’ve commonly seen it referred to as the technology which allows you to customising field and list rendering but that is really the Display Template functionality.

In a nut-shell JSLink simply means “link to my JavaScript file”

This is basically a URL to a JavaScript file. It doesn’t really matter where this file is (it could just as easily be in a document library or the Layouts folder). There are a vast number of objects you can attach JSLink references to but the ones we are really interested are:

  • Site Columns
  • Content Types
  • List Views
  • List Forms (e.g. New / Edit / Display forms)
  • List View Web Parts
  • List Form Web Parts

This gives us the full battery of places that we need in order to get our JavaScript in the right place at the right time, some of which are clearly desirable for different reasons.

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)

This allows you to easily make sure that your JSLink files are targeted correctly (whether you are provisioning them to a specific library, or want to make sure your _layouts URL is constructed appropriately).

You can also apply more than one JSLink reference at a time by separating each reference with the pipe | symbol. So if you wanted to include two custom JSLink files on a field you might use the following attribute:

JSLink=~sitecollectionlayouts/MJH/JSLink1.js|~sitecollectionlayouts/MJH/JSLink2.js

Applying your JSLink References
You have a whole range of different options for applying your JSLink to the different objects, and this will largely depend on where you want your customisations to be applied.

If you are creating a new custom field type then you would implement it at the Site Column level. If you want to do something specific such as cascading drop-downs then you might want to do that at the Content Type or List (form) level.

If you are doing a one-off demo in an environment where you don’t have a high level of permissions then you can apply the JSLink references to the List View or Form Web Parts (although appreciate that this obviously doesn’t scale particularly well as you would have to manually apply it to each web part).

You can apply them using XML as part of your Site Column, Content Type or List View definitions. Each of these contains a JSLink attribute which you can use to populate a URL

JSLink=~sitecollectionlayouts/MJH/JSLink1.js

You can also apply them to the above, as well as list forms using Server Side Code (I’m not sure if there is a client side object model equivalent).

SPList list = web.Lists.TryGetList(“My List”);
if (list != null)
{  SPForm editForm = list.Forms[PAGETYPE.PAGE_EDITFORM];
  editForm.JSLink = “~sitecollectionlayouts/MJH/JSLink1.js”;
}

You can even do this in PowerShell if you are properly hardcore 🙂

$web = Get-SPWeb https://teamsite.mjh
$field = $web.Fields[“MJHSampleField”]
$field.JSLink = “~layouts/MJH/JSLink1.js”
$field.Update($true)

And finally you can set this in the List View Web Part or List Form Web Part using the web part properties:

Add your JSLink reference to Web Part properties

There is also a final option where it seems you can create re-usable templates by uploading your templates into the Master Page Gallery so they appear as new “View Types” when users are creating new Views for their lists, but more about that in Part 5!

So that covers all of the basics about what JSLink actually is, how the URLs are constructed and how you can apply them. In the next few parts we will be looking at the sample code and walking through some real-world examples of how you can use JSLink along with Display Templates to implement custom field and view rendering.

Next: Part 2 – Changing how individual fields display

Why I am never buying an EE / Orange / T-Mobile mobile contract again

I admit this blog post is a bit of a rant, but to be honest I need to get this off my chest (and warn other people).

I’ve been an EE customer for about 4 years now (and for those people living under a rock, EE are the new “Everything Everywhere” brand formed from the UK merger between Orange and T-Mobile). I originally had a 2 year contract with T-Mobile and about 18 months ago switched over to Orange as a business account.

Now don’t get me wrong, some of the service has been first rate. When I first received my Nokia Lumia 800 there were some teething issues with battery life resulting in my first phone getting bricked. Orange Business Customer Services were awesome, they couriered me a new phone next day and within 24 hours I had a brand new replacement phone.

But unfortunately, that is where the satisfaction ends

Problem #1 – Tethering and Hidden Costs
This is a major bug-bear of mine, as when I first went into the store to sign up for a contract with Orange (this was before the big EE re-brand) I specifically told them that I needed 3 things:

  • High data usage so I could use my phone for occasional tethering
  • High minutes count across mobile and landlines
  • High text limit as I use a LOT of text messages

For those of you who don’t know “tethering” is where you can turn your mobile phone into a Wi-Fi Hot-Spot so if you have a 3G (or even 2G / GSDM connection) you can still get a basic internet connection on your laptop. I used this on my old T-Mobile contract frequently (with the good old HTC HD2) and this has been a staple feature on many phones for a long long time.

Now .. I’m not expecting to use this feature every day, but if I desperately need to get / send an email on my laptop while I’m on the train, or in a remote rural location (I live in the country, most pubs and cafes in the area don’t have Wi-Fi) then my phone is the only choice.

So .. I was a little annoyed to find that when I tried to use “Internet Sharing” it didn’t work. When I contacted Orange they told me that I had to buy a separate bundle (for a minimum of £10 per month) and it would have a completely separate data allowance to my normal phone.

Now, this annoyed me on principle but to add salt to the wound the customer services representative actually tried to tell me that “laptop data is different to mobile data”. She tried to keep this up for almost 10 minutes until I told her I worked in IT and she back-tracked and told me “actually, it is just company policy”.  So not only did they have a crappy policy but the person on the phone actually lied to me until I called her out on it!

Thankfully when Windows Phone 7.8 rolled out it all started working, I can only presume because WP7.8 and WP8 both have updates directly from Microsoft (which meant Orange / EE couldn’t block core phone functionality any more).

Problem #2 – Intermittent connections .. loss of data, missed calls, missed text messages
This has been on-going for over a year now and seems to be quite intermittent.

Sometimes I miss text messages (they don’t arrive for several hours). Sometimes I get missed calls (I apparently have full phone signal but the phone doesn’t ring .. I just get a voicemail notification after someone apparently tried to call). I have also experienced loss of data connection. The phone tells me I have full 3G / 3G+ (HSPDA) connection but I cannot access emails or the internet (or any of the app / hub functions which require the internet).

Occasionally rebooting the phone will fix it, but sometimes it doesn’t. I’ve had to borrow my wife’s phone (also a Lumia 800) before now to make a phone call because my phone won’t connect when I try to dial someone.

This isn’t even a signal range issue .. I’ve had this in town centres and in the middle of central London (and again, the phone says I have full 5-bar 3G+ signal).

Problem #3 – After a warranty repair they won’t give me my phone back
This is the major issue I have with EE and is really the last straw. They seem to have some weird company separation between the “services” side of the business (who run the contracts and provide the connections) and the “store” side of the business (with high-street shops, staff and physical phones).

Normally this would be “their” problem, but unfortunately it has become “my” problem.

I was in Tunbridge Wells for the weekend and saw the EE store as I was passing. I thought I would save them some time and just drop my phone in for repair. Last time they couriered me a new phone within 24 hours so I figured it would be just as quick an easy … my mistake.

Firstly it took over 2 weeks for my phone to get repaired, but the crunch came when I got an email telling me my phone was “ready for collection from the store” … erm .. I work in London.

Luckily I managed to convince my wife to go on a mission to try and get my phone for me (armed with photo ID and proof of address) .. they refused to hand over the phone saying that the account holder must receive the phone “in person”.

Next I called the store directly and asked what I could do to get my phone back. Could I write a letter authorising someone else to collect the phone on my behalf? Could they post or courier to the phone to me (I’m happy to pay postage). They bluntly refused .. their excuse? “sorry, company policy”.

So finally I phoned my Business Customer Services. They were (to their credit) slightly horrified that the store was treating me like this (and admitted that if I had called them they would just courier me a brand new replacement phone). Unfortunately, because I’d handed my phone in to the store they couldn’t do this anymore. They contacted the store, but because it’s a separate company had no authority and got the same line of BS that I did “the account holder must turn up in person”.

So now I either have to take time off work, or re-schedule my weekends to get myself to their store in person, just so they would give me back my phone (which I’m paying them for each month as part of my contract).

So .. customer dissatisfaction throughout .. I am deeply unimpressed and will most definitely NOT be using Orange, T-Mobile or “EE” again in the future (and if I have my way, neither will my family or friends either!)

Customising the Content Search Web Part – Part 2 – Custom Display Templates with JavaScript

This is the second post in a series I will be writing on the Content by Search Web Part (aka CSWP).

  1. What you get in the box
  2. Custom Display Templates with JavaScript (this post)
  3. Going Old Skool with XSLT
  4. Packaging & Deployment in Visual Studio

So if you’ve read Part 1 (what you get in the box) then you should have a pretty good idea of what the CSWP can do by now and what Display Templates and Property Mappings are (if you don’t then go back and read Part 1 .. I won’t be explaining them again).

So now we move onto the brave new world of building and defining your own custom Display Templates. The first thing you need to know is that Display Templates are stored in the Master Page Gallery (No, I don’t know why) specifically in a sub-folder called “Display Templates”.

Item Templates in the Master Page & Page Layouts Gallery

In here you will find two types of file:

  • HTML files – these are the actual Display Templates (and what you will copy/create when you create your own custom template)
  • JS files – These are the “compiled” JavaScript files which are automagically created by SharePoint when you add / modify one of the HTML templates

Display Template basics – Using JavaScript
The out of the box display template files actually include some pretty useful comments which tell you how this works, but basically you have two “tokens” that you need to use:

To Write JavaScript explicitly you need to use HTML comments with #_ and _# at each end. This tells SharePoint that it needs to take whatever is inside these tokens and “compile” it into JavaScript in the finished file. For example:

<!–#_ var myString = ‘Hello World’; _#–>

This allows you to write pretty much any JavaScript that you like. You can use this JavaScript to retrieve values from your Property Mappings as follows:

<!–#_ var linkURL = $getItemValue(ctx, “Link URL”); _#–>

In the above example “Link URL” is the name of the Property Mapping. If you then want to use those variables in your HTML you simply wrap then in =#_ and _#= tokens. For example:

<a href=”_#= linkURL =#_”>
  <span> _#= myString =#_</span>
</a>

It really is that simple!

But before we look at actually creating a new Display Template, what we really need is a problem to solve (I find it helps to focus the mind) ..

A suitable problem – Pictures, Publishing Pages and Image Renditions, oh my!
One of the great new features in SharePoint 2013 is “Image Renditions” (explained in great detail by Waldek Mastykarz). The cool thing is that if you have registered an Image Rendition with a desired width / height then you can include those as URL attributes and SharePoint will resize the image server side! This is a fantastic feature, it (drastically) reduces image sizes and ensures that the output is consistently rendered.

The out of the box display templates will automatically use these Image Renditions (the “Large Picture” template for example will ask SharePoint for an image which is 468×220, which matches one of the out of the box image renditions).

However when you try to use Image Renditions with the CSWP then you get some pretty odd results. To demonstrate this I have uploaded 4 photos from one of my holidays a few years back. I then created a Publishing Page for each photo and selected different Image Renditions for each page.

I then displayed then using the CSWP using the “Large Picture” item template and here are the results:

 

CSWP displaying the actual photos in the Asset Library

 

CSWP displaying the Publishing Pages (and pulling the associated image)

As you can see the second one looks a bit screwy as all of the images are different sizes. So what on earth is happening? Well, on checking the URL for one of the images which is being returned I can see that the image URL is correctly picking up the including the Rendition ID that I picked on my publishing page.

..photos/DSC_1002.JPG?RENDITIONID=1&width=468&height=220

This is bad, because when SharePoint renders an image it will first look for the RenditionID and if it finds one it will ignore the width and height attributes!

The solution – Custom Display Template
So in order to fix this we need to create ourselves a custom Display Template so we can strip out that RenditionID attribute using JavaScript so the images served by SharePoint come out in the correct size.

So first off, I went and downloaded a copy of the Item_LargePicture.html file (which I used as my starting point) and renamed it (to “Item_LargePictureFixed.html”).

The next thing to do is to rename the <title> attribute in the file. This is what gets used in SharePoint to identify the template in the CSWP web part properties.

<title>Large Picture (FIXED)</title>

Now, I also wanted to add some more detail to my display template as just showing the title wasn’t that great (bringing back the publishing date and author for the page would be cool) .. and it also allows me to demonstrate how the Property Mappings work.

So the next thing is to look for an XML element near the top of the file called mso:ManagedPropertyMapping. This contains all of the Property Mappings that the CSWP will pick up when your template is in use.

When you define Property Mappings you can also define the search properties it should look for and the format you need to use is:

<Mapping Name>:<Search Property1>;<SearchProperty2>

Each mapping is separated by a comma (,) so my custom mappings were

  • Image Title (mapped to “Title”)
  • Image Date (mapped to “ImageDateCreated” and “LastModifiedTime”)
  • File Author (mapped to “Author”)

‘Image Title’:’Title’,’Image Date’:’ImageDateCreated;LastModifiedTime’,’File Author’:’Author’

Don’t forget that our properties map to Search Properties .. so if the field isn’t being indexed by Search then you won’t be able to use it!

Once we had our mappings in place we can pull it all into variables using JavaScript. This includes a (slightly nasty) sub-string function to pull out any URL attributes for the Image URL

<!–#_

var pictureURL = $getItemValue(ctx, “Picture URL”);

// get the picture URL as a string
var cleanPictureURL = pictureURL.toString();

// check if it contains any query string arguments
if(cleanPictureURL .indexOf(“?”) != -1)
{
// if it does, then strip them out
var renditionIndex = cleanPictureURL .indexOf(“?”);
cleanPictureURL = cleanPictureURL .substring(0, renditionIndex);
}

// add the width/height attributes back in for the image renditions
cleanPictureURL = cleanPictureURL + “?width=468&height=220”;
// get our three other property values
var imageTitle = $getItemValue(ctx, “Image Title”);
var imageDate = $getItemValue(ctx, “Image Date”);
var fileAuthor = $getItemValue(ctx, “File Author”);

_#–>

Once that was done all we needed was to make sure our variables were used in the right parts of the HTML. I then uploaded the HTML file (which effectively installs the new Display Template) and wired it up in the Web Part.

New Display Template with new Property Mappings being displayed
New “fixed” Display Template with correct sized images, and new property mappings being displayed

If you want to take a closer look then you can download the example HTML file here:
https://sdrv.ms/172o9rM

So that is it for CSWP Display Templates .. in part three we will look at going old school with XSLT rendering.

Proud first time father :)

Sorry my activity has been a little slow, but I am extremely proud to announce the birth of my daughter (Amy) last week (mum and baby both doing great!).

Being a new dad is all very scary (and very, very tiring!) so please appreciate I might not be able to rattle out as much new content. Hopefully (when things settle down) I’ll be back and writing up a bunch of cool stuff (so much to write about!)

DIWUG Magazine

The 10th Edition of the Dutch Information Worker Group (DIWUG) has been issued and I was honoured to be one of the guest authors.

For those who don’t know the DIWUG magazines are released 2-3 times a year and contain a whole range of excellent content for IT Pros, Developers and End Users.

In this edition (April 2013) you can find me writing about Display Templates in the Content Search Web Part.

The full star-studded line up can be found below:

  • Custom Forms in SharePoint 2013 Workflows with Visual Studio 2012 – Andrew Connell
  • Pimp your SharePoint search results – Stefan Strube
  • SharePoint, Yammer and the social landscape – Chris Johnson
  • Protecting SharePoint 2013 with DPM 2012 – Sam Hassani
  • Strategic Thinking and SharePoint – Jaap Zwart
  • Custom Display Templates for the Content Search Web Part – Martin Hatch
  • Optimizing SQL Server 2012 for SharePoint 2013 – Brian Alderman
  • Enterprise Social Case Management, where Workflow and User Engagement meet – Marc Vanderheyden
  • You can grab a PDF of the magazine or an e-Reader edition from their website:
    https://www.diwug.nl/e-magazines/

    « Older Entries Recent Entries »