Display templates can only be stored in several places of SharePoint to get loaded. I was wondering if I will be able to inject this mechanism or if I will be able to provide a display template directly out of a provider hosted app.
Normally Display Templates will be uploaded to every site collection inside the master page catalog, but with a little tweak those can be loaded from everywhere in the world as long they are accessible via a web server.
The local display template
Display templates will be executed not on the server, but on the client. Embedding remote scripts is something we do all the day. If we use jQuery or SPServices, for example.
To load a display template we just need to use the function:
// Function to embed remote javascript function loadScript(url, callback){ var script = document.createElement("script") script.type = "text/javascript"; if (script.readyState){ //IE script.onreadystatechange = function(){ if (script.readyState == "loaded" || script.readyState == "complete"){ script.onreadystatechange = null; callback(); } }; } else { //Others script.onload = function(){ callback(); }; } script.src = url; document.getElementsByTagName("head")[0].appendChild(script); } // load remote display template inside SharePoint loadScript("http://localhost:9000/scripts/test.js", function(){ })
At the end of this snippet all I defined the locations where the remote display template is located. In my case it is on my local web server. The only thing we do now is to upload this script to the display templates instead of the code for the display template.
This script we reference in the JSLink property of a list view web part, for example.
In my case the path is “~sitecollection/_catalogs/masterpage/display template/loadExternal.js” .
The remote display template
Next up we need to add the code for the “real” display template. The following snipped just register a custom action on a document library.
var registerCallout = function () { itemCtx = {}; itemCtx.Templates = {}; itemCtx.BaseViewID = 'Callout'; // Define the list template type itemCtx.ListTemplateType = 101; itemCtx.Templates.Footer = function (itemCtx) { return CalloutRenderFooterTemplate(itemCtx, AddCustomAction, true); }; SPClientTemplates.TemplateManager.RegisterTemplateOverrides(itemCtx); } var AddCustomAction = function(renderCtx, calloutActionMenu) { // Add custom action calloutActionMenu.addAction(new CalloutAction({ text: "Custom Action", tooltip: 'This is your custom action', onClickCallback: function () { console.log('Alert from custom action'); } })); } SP.SOD.executeOrDelayUntilScriptLoaded(registerCallout, "callout.js");
Now let’s see if the custom display template is loaded.
There you go the custom action is loaded from the remote web site to the SharePoint site and it is registered correctly.
Conclusion
I think this remote loading of display templates is pretty useful during development or if you like to create a display template repository within your organisation. Those remote display templates are simply easier to maintain.
Another use case might be that you keep your display templates inside the provider hosted website and just provision the load of the external javascript to SharePoint. Once again, you can upgrade the display templates without upgrading the app. Especially if the app is hosted on multiple environments.
For me it speeded up the development process, but keep an eye on possible security issues. As cool as it is. Scripts can be easily hacked and replaced by malicious code if you embed it directly from the internet.