Files stored in Office 365 or SharePoint Server 2013 can be shared with other people. Although this isn’t new, it is a great feature and never has been easier to use.
Governance-wise sharing can be a challenge, because you’re unable to see, when looking at the files in a document library, which files are shared. Ofcourse the document library settings page can give an overview, but that’s about 4 clicks too far away.
On the other hand OneDrive for Business shows which files are shared by you with a nifty icon.
It would be nice to see the same behavior of showing which files are shared, or in the old fashioned term showing unique permissions, on a file outside OneDrive for Business.
This can be accomplished by implementing two components: a custom rendering template using javascript and a column to show the icon in.
The column is used to override in the template to show the icon when the file is shared. This one is created manually, because of this demo purpose.
Just create a field as you normally should, name it ‘Sharing’ and choose a ‘Single line of text’ type. To be able to see this column in the view you’re working with adjust this view to show the ‘Sharing’ column.
The custom rendering template is created using javascript. The first step is to define:
- the field to override: ‘Sharing’
- a render method: ‘ITIdea.SharingFieldOverride’
- for the view you want to control, in this case the ‘View’ of the field.
Finally the RegisterTemplateOverrides method is called to apply the custom view.
(function () { var overrideField = {}; overrideField.Templates = {}; overrideField.Templates.Fields = { "Sharing": { "View": ITIdea.SharingFieldOverride } }; SPClientTemplates.TemplateManager.RegisterTemplateOverrides(overrideField); })();
The above function is a so called immediately-invoked function expression (or IIFE) or anonymous self-executing function.
All that is left to be done is to implement the render method ‘ITIdea.SharingFieldOverride’.
The most exiting thing here is to determine the unique permission of a file. For this a REST call is used. This call is fired for every document in the view so this is probably the reason it isn’t implemented by default.
First the REST endpoint is put together using the url, list id and the id of the current item. Then the Ajax call is fired and depending on the unique role assignments of the file some HTML is formatted.
ITIdea.SharingFieldOverride = function (ctx) { var url = _spPageContextInfo.webAbsoluteUrl; var requestUri = url + "/_api/web/lists('" + _spPageContextInfo.pageListId + "')/items(" + ctx.CurrentItem['ID'] + ")/hasuniqueroleassignments"; var returnHtml = ""; jQuery.ajax({ url: requestUri, type: 'GET', headers: { 'ACCEPT': 'application/json;odata=verbose' }, success: function (result) { if (result.d.HasUniqueRoleAssignments) { returnHtml = "<a href='#' onclick='onSharingHintClicked(this); return false;' aria-label='Shared with some people'>"; returnHtml += " <span style='height: 16px;width: 16px;display: inline-block;overflow: hidden;position: relative;'>"; returnHtml += " <img src='/_layouts/15/images/spcommon.png?rev=23' title='Shared with some people' style='left:-254px;top:-30px;position:absolute'/>"; returnHtml += " </span>"; returnHtml += "</a>"; } else { returnHtml = "<a href='#' onclick='onSharingHintClicked(this); return false;' aria-label='Only shared with you'>"; returnHtml += " <span style='height: 16px;width: 16px;display: inline-block;overflow: hidden;position: relative;'>"; returnHtml += " <img src='/_layouts/15/images/spcommon.png?rev=23' title='Only shared with you' style='left:-200px;top:-30px;position:absolute'/>"; returnHtml += " </span>"; returnHtml += "</a>"; } } }); return returnHtml; };
The style on the html elements are the exact style items from OneDrive for Business to create the same user experience.
I used inline styles instead of the classes OneDrive uses, becasue of the early loading of this javascript file. It loads that early in the page lifecycle the css files aren’t there yet.
The last things to do are to upload the javascript file to the style library (or some other place) and reference the file at the list view using the JSLink property. Since jQuery was used in the javascript file, a reference to jQuery is also necessary to make things work. Note that dependent files have to be referenced first, so jQuery first, use a ‘|’ as separator and then reference the custom rendering template, like ‘~sitecollection/Style Library/_itidea_jslink/jquery-2.0.0.js|~sitecollection/Style Library/_itidea_jslink/SharingTest.js’.
~sitecollection refers to the url of the parent site collection.
The final result is the same as OneDrive for Business, shared documents show the ‘Shared with some people’ icon, others show ‘Only shared with you’ icon:
Summary
Custom rendering templates are a neat way of showing, in this case, additional information. A ton of other stuff can be done with it, showing readonly fields in edit mode, implement custom validation and much more.
As I mentioned previously this functionality is probably an intensive process when a lot of documents are stored in the library, because the call is fired for every document.
Showing if an item is shared works as wel on files and folders. Keep in mind that showing if an item in shared is an item thing. What I mean to say is that when a sharing icon is shown at a folder level, it doesn’t mean all the files in the folder are shared. Out-of-the-box OneDrive for Business functionality.
Please note the final result is NOT the same as done for the “OneDrive for Business” document library on My Sites.
Microsoft is referencing the built-in PrincipalCount field (https://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spbuiltinfieldid.principalcount.aspx) for defining if a securable object is shared or not, and this field is not available on any other list. You could add the field to a list, but would still require an event to update its value.