Friday, September 30, 2016

Hide columns from (grouped) ListView with conditional formatting

Calculated Fields in SharePoint Lists enable conditional (rich) formatting of raw data from one or more other columns in the same List. This is typically used to ‘business-beautify’ the data display for the end-users. Example is to render ‘Green/Orange/Red’ headlights for immediate visual reference, based on the raw ‘text’ data of a status/progress field. In such usage setup, only the conditional columns should be visible for end-users, not the raw data columns. However, the execution of SharePoint ListView requires that the source data columns are included in the view, otherwise the conditional columns lack their source data in the listview and render empty (or with an error, dependent upon formula).
Hide the columns from display
There are multiple approaches to still hide the ‘raw data columns’ from end-user visibility. My preference is for a CSS-based approach: hide via nth-child selector. For SharePoint 2010 + IE an extension is needed on top of this: IE only supports nth-child as of IE9, but the standard DocumentMode for SharePoint 2010 is IE8 (multiple of the standard SharePoint 2010 functionalities require this, and give browser-problems with document mode later than IE8). Luckily via jQuery the nth-selector is also available for the older IE-versions. The full setup to hide columns in a listview is therefore 2-staged:
  1. CSS:
    /* * Below CSS-selector is supported in >= IE9, Chrome, FF; but not supported in IE8 */ .ms-listviewtable th:nth-child(3), … .ms-listviewtable td:nth-child(3), … { display:none; } /* * This to compensate with non-support of nth-child in IE8 (compatibility mode) */ .ms-listviewtable th.Hide, .ms-listviewtable td.Hide { display:none; }
  2. JavaScript:
    function HideRawDataColumns() { $(‘.ms-listviewtable th:nth-child(3)’).addClass(‘Hide’); $(‘.ms-listviewtable td:nth-child(3)’).addClass(‘Hide’); …. } $(document).ready(function () { HideRawDataColumns (); });
Grouped Views
Above approach breaks for ListViews with one or more Group By applied. The cause is in the deferred loading behavior by the ListView rendering: the data is delayed loaded only when the user clicks to open a group header, and also delayed rendered. For the fully CSS-based approach, this is not an issue: the CSS will be applied for all elements, also when later added to the rendering. The formula is a bit different though, as you need to distinguish between the ‘Grouping’ rows and the ‘Data’ rows. However, for SharePoint2010 + IE it is different. On initial page load moment, the data rows might not be present yet in the DOM, and the IE8 / JavaScript approach to explicitly determine + tag the TD-childs will fail. Solution is to delay the CSS-tagging to after the moment that the data-rows are actually added to the DOM. This requires to hook into the standard ListView javascript handling.
  1. CSS:
    /* * Below CSS-selector is supported in >= IE9, Chrome, FF; but not supported in IE8 */ .ms-listviewtable th:nth-child(3), … .ms-listviewtable td:nth-child(3), .. .ms-listviewtable tbody:not([groupString]) td:nth-child(3), … { display:none; } /* * This to compensate with non-support of nth-child in IE8 (compatibility mode) */ .ms-listviewtable th.Hide, .ms-listviewtable td.Hide { display:none; }
  2. JavaScript:
    var HideFormatColumnsListView = window.HideFormatColumnsListView || {}; HideFormatColumnsListView.UI = function () { function HideRawDataColumns() { $(‘.ms-listviewtable th:nth-child(3)’).addClass(‘Hide’); $(‘.ms-listviewtable td:nth-child(3)’).addClass(‘Hide’); …. if ($.prototype.base_UpdateCtxLastSelectableRow === undefined) { $.prototype.base_UpdateCtxLastSelectableRow = UpdateCtxLastSelectableRow ; UpdateCtxLastSelectableRow = function(clvpCtx, clvpTab) { $.prototype.base_UpdateCtxLastSelectableRow(clvpCtx, clvpTab); var groupRow = clvpCtx.clvp.tBody; if (groupRow !== null && groupRow !== undefined) { $('td:nth-child(3)', $(groupRow)).addClass('Hide'); … } }; } } var ModuleInit = (function() { ExecuteOrDelayUntilScriptLoaded(function () { HideRawDataColumns() }, "inplview.js"); })(); }();