Ok.. success ! In case someone else is struggling here is the script.
General
- Works in MDS and non MDS mode if deployed as per script comments.
- An old method of hiding the column using jQuery is included but commented out (ie. the OnPostRender has been commented). I thought it might be useful to someone.
- I have not done extensive testing yet so mileage and performance may vary.
When not in QuickEdit -
- Displays title in name column on document libraries.
- Hides the title column. (Which must be in the view).
- Document menu and previews work.
- Sorting is still using the filename. (Could be a further regex in
the header to change this ?)
In QuickEdit -
- Shows the columns as normal allowing for updating of Title and Filename.
Drop me a note if you have any improvements to offer !
function $_global_kgjslinktitlefordocview() {
//jslink script to change a document library view so that Name of each document uses the Title value.
//Requires that Title is in the view, so the display template hides the Title field.
//Deployed straight to _layouts as file kgjslinktitlefordocview.js
//Used jslink property of listview as clienttemplates.js|kgjslinktitlefordocview.js
//Special note : do not use ~layouts token. It is bugged and adds a script reference in the page that is missing a leading /.
// - This breaks MDS as registerinit function cant match the path.
//The $_global_ wrapper function ensures that this works in MDS enabled sites.
Type.registerNamespace('KG');
KG.jslink_linktitle = KG.jslink_linktitle || {};
KG.jslink_linktitle.Templates = KG.jslink_linktitle.Templates || {};
KG.jslink_linktitle.Functions = KG.jslink_linktitle.Functions || {};
KG.jslink_linktitle.Functions.linkOnPostRender = function () {
//This function has been left in as an alternate example.
//I did not like that the column appears for a moment before it gets hidden.
//Function to hide the Title column on PostRender using jQuery based on the code by Muawiyah Shannak.
//The callback routine is because in my environment I am registering jQuery as on-demand.
var callback_linkonpostrender = function () {
//Hide "Title" column if not in QuickEdit mode
if (!this.ctx.inGridMode) {
var cell = jQuery("div [displayname='Title']").closest('th');
var cellindex = typeof cell.cellIndex;
if (cellindex != null && cellindex != 'undefined') {
var cellIndex = cell[0].cellIndex + 1;
jQuery('td:nth-child(' + cellIndex + ')').hide();
jQuery('th:nth-child(' + cellIndex + ')').hide();
}
}
}
var namespace = "$_global_kgjquery";
var key = "kgjquery.js";
var bSync = true;
if (typeof $_global_kgjquery == 'undefined') {
SP.SOD.executeFunc(key, namespace, function () {
console.log(key + ": Type available (" + namespace + ")");
}, bSync);
SP.SOD.executeOrDelayUntilScriptLoaded(callback_linkonpostrender(), key);
}
else {
console.log(namespace + " found so jQuery should be loaded.");
callback_linkonpostrender();
}
}
KG.jslink_linktitle.Functions.getDefaultFieldHtml = function (renderCtx, field, listItem, listSchema) {
//Copy Paste of Jim Browns awesome helper function to return default CSR field rendering
var renderingTemplateToUse = null;
var fieldRenderMap = {
Computed: new ComputedFieldRenderer(field.Name),
Attachments: new AttachmentFieldRenderer(field.Name),
User: new UserFieldRenderer(field.Name),
UserMulti: new UserFieldRenderer(field.Name),
URL: new UrlFieldRenderer(field.Name),
Note: new NoteFieldRenderer(field.Name),
Recurrence: new RecurrenceFieldRenderer(field.Name),
CrossProjectLink: new ProjectLinkFieldRenderer(field.Name),
AllDayEvent: new AllDayEventFieldRenderer(field.Name),
Number: new NumberFieldRenderer(field.Name),
BusinessData: new BusinessDataFieldRenderer(field.Name),
Currency: new NumberFieldRenderer(field.Name),
DateTime: new DateTimeFieldRenderer(field.Name),
Text: new TextFieldRenderer(field.Name),
Lookup: new LookupFieldRenderer(field.Name),
LookupMulti: new LookupFieldRenderer(field.Name),
WorkflowStatus: new RawFieldRenderer(field.Name)
};
if (field.XSLRender == '1') {
renderingTemplateToUse = new RawFieldRenderer(field.Name);
}
else {
renderingTemplateToUse = fieldRenderMap[field.FieldType];
if (renderingTemplateToUse == null)
renderingTemplateToUse = fieldRenderMap[field.Type];
}
if (renderingTemplateToUse == null)
renderingTemplateToUse = new FieldRenderer(field.Name);
return renderingTemplateToUse.RenderField(renderCtx, field, listItem, listSchema);
}
KG.jslink_linktitle.Functions.renderHeaderTemplateForLibraries = function (renderCtx, fRenderHeaderColumnNames) {
//Set the amount of views to display on the change view control (viewData.length -3 for all)
var viewData = eval(renderCtx.ListSchema.ViewSelectorPivotMenuOptions);
ClientPivotControl.prototype.SurfacedPivotCount = viewData.length - 3;
//Get HTML from standard RenderHeaderTemplate function
var htmlheader = RenderHeaderTemplate(renderCtx, fRenderHeaderColumnNames);
//If not in QuickEdit then try to RegEx replace out all of the header for the chosen column
// (Note : Uses a negative lookahead to make sure its the closest <th tag.)
if (!renderCtx.inGridMode) {
var re = new RegExp('(<th (?:(?!<th ).)*DisplayName=\\"Title\\".*?<\/th>)', 'g');
var match = re.exec(htmlheader);
var replaced = htmlheader.replace(re, "");
return replaced;
}
//If in QuickEdit then just display default header
return htmlheader;
}
KG.jslink_linktitle.Functions.renderBodyTemplateForLibraries = function (renderCtx) {
//If not in QuickEdit then try to modify the renderCtx.ListSchema.Field array to remove the field that we dont want rendered in the body HTML.
if (!renderCtx.inGridMode) {
var temptitlefield = {};
var temptitlefieldnumber = -1;
//In the standard renderBodyTemplate function, the ListSchema.Field array seems to get used to build the <td> values for each field.
//Sneaking in and removing the field that we dont want displayed in the body and then calling the default RenderBodyTemplate seems to work.
for (var i = 0; i < renderCtx.ListSchema.Field.length; i++) {
if (renderCtx.ListSchema.Field[i].FieldTitle === "Title") {
temptitlefield = renderCtx.ListSchema.Field[i];
temptitlefieldnumber = i;
renderCtx.ListSchema.Field.splice(i, 1);
break;
}
}
//Get HTML from standard RenderBodyTemplate function
//(using our now modified renderCtx with the field removed from ListSchema if not in QuickEdit)
var htmlbody = RenderBodyTemplate(renderCtx);
//Here we reverse our change if we made one. Without this the title field was readonly in QuickEdit until refreshing the page.
//I assume the renderCtx object is reused so we add the Title field back in.
if (temptitlefieldnumber != -1)
{
renderCtx.ListSchema.Field.splice(temptitlefieldnumber,0,temptitlefield);
}
return htmlbody;
}
//Assuming we are in QuickEdit we just use default RenderSPGridBody
var gridbody = RenderSPGridBody(renderCtx);
return gridbody;
}
KG.jslink_linktitle.Templates = {
'Header': KG.jslink_linktitle.Functions.renderHeaderTemplateForLibraries,
'Body': KG.jslink_linktitle.Functions.renderBodyTemplateForLibraries
}
KG.jslink_linktitle.Templates.Fields = {
//'Title': {
// 'View': function () { return null; }
//},
'LinkFilename': {
'View': function (ctx) {
//Use Jim Browns helper function to get whatever the base HTML for the field should be.
var html = KG.jslink_linktitle.Functions.getDefaultFieldHtml(ctx, ctx.CurrentFieldSchema, ctx.CurrentItem, ctx.ListSchema);
//Locate the LinkFilename display text in the html.
var filename = ">" + ctx.CurrentItem.FileLeafRef.substring(0, (ctx.CurrentItem.FileLeafRef.lastIndexOf("."))) + "<";
//If not in QuickEdit and if Title exists and is not blank then use the Title as the LinkFilename display text.
if (!ctx.inGridMode && ctx.CurrentItem.Title != '' && ctx.CurrentItem.Title != '' && typeof ctx.CurrentItem.Title != "undefined") {
var newhtml = html.replace(filename, ">" + ctx.CurrentItem.Title + "<");
return newhtml;
}
//Otherwise return default HTML.
return html;
}
}
}
//This was my first attempt by using jQuery to hide the column during PostRender.
//KG.jslink_linktitle.OnPostRender = KG.jslink_linktitle.Functions.linkOnPostRender;
KG.jslink_linktitle.BaseViewID = 1;
KG.jslink_linktitle.ListTemplateType = 101;
//Make the magic happen....
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(KG.jslink_linktitle);
} $_global_kgjslinktitlefordocview();