Jul 5, 2013

Best way to hide columns in SharePoint 2010 for Display form, Edit form or New form

I always thought that if you need to hide a column in SharePoint 2010, you only had several options, each of which has limitations:
  1.   Set the column to Hidden in the content type - Hides the column in all forms
  2.  Customize each form page with JavaScript to hide the columns of interest - Very tedious and error prone
  3. Use InfoPath to customize the forms - Lots of compatibility problems and not available in SharePoint Foundation
But the other day it dawned on me that a great fourth solution exists: change the FIELD SCHEMA!

I saw the field schema had more granular properties of ShowInDisplayForm, ShowInEditForm, ShowInNewForm, etc.  You can edit these via code, SharePoint Manager or PowerShell.

I even implemented a page that can change these properties entirely via the Client Object Model for those using SharePoint Online (Office 365) or who simply don't have root access to the server.

Here's the HTML:



<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js">
</script>
<script type="text/javascript">


ExecuteOrDelayUntilScriptLoaded(buildListMenu, "sp.js");

function buildListMenu() {
  this.clientContext = new SP.ClientContext.get_current();
  var oListCollection = this.clientContext.get_web().get_lists();
  
  this.listCollection = clientContext.loadQuery(oListCollection);
   clientContext.executeQueryAsync(Function.createDelegate(this, this.onSiteQuerySucceeded), Function.createDelegate(this, this.onSiteQueryFailed));
  this.listCollectionNotifyId = SP.UI.Notify.addNotification("Cargando listas",true);
}

function onSiteQuerySucceeded() {
   SP.UI.Notify.removeNotification(this.listCollectionNotifyId);
 for(var i = 0; i < this.listCollection.length; i++) {
    var list = listCollection[i];
    jQuery('#listMenu').append("<option value='"+list.get_id().toString()+"'>"+list.get_title()+"</option>");
      
 }
 
 changeList(document.getElementById("listMenu"));
 
}

function onSiteQueryFailed() {
SP.UI.Notify.removeNotification(this.listCollectionNotifyId);
 alert("Error cargando listas");
}

function changeList(selectMenu) {
   var listId = selectMenu.value;
   retrieveListColumns(listId);
  
}

function retrieveListColumns(listId) {
    this.clientContext = new SP.ClientContext.get_current();
    var oWebsite = clientContext.get_web();
    var oList = oWebsite.get_lists().getById(listId).get_fields();

    this.fieldCollection = clientContext.loadQuery(oList);

    clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}

function onQuerySucceeded() {

    var listInfo = '';
    this.fieldArray = new Array();
    this.attributeArray = ["ShowInDisplayForm",
          "ShowInNewForm",
          "ShowInEditForm",
          "ShowInListSettings",
          "ShowInVersionHistory",
          "ShowInViewForms"]; 
                    
    

 clearColumnsTable();
    
    // for every field
    for (var i = 0; i < this.fieldCollection.length; i++) {
        var oField = this.fieldCollection[i];
        
        // only interested in visible fields
        if(!oField.get_hidden()) {
        this.fieldArray[oField.get_id().toString()] = new Array();
        var currentAttributeArray = new Array();
        
          this.fieldArray[oField.get_id().toString()]["SPObject"] = oField;
           
           var xmlDoc = parseSchemaXml(oField.get_schemaXml());
           this.fieldArray[oField.get_id().toString()]["xmldoc"] = xmlDoc;
           
           // create row for checkboxes 
           var newRow = jQuery('<tr/>');
           newRow.append("<td>"+oField.get_title()+" ("+oField.get_internalName()+")</td>");
            
           // create checkboxes
           for(var j = 0; j < this.attributeArray.length; j++) {
              var attribute = this.attributeArray[j];
              currentAttributeArray[attribute] =  xmlDoc.documentElement.getAttribute(attribute) == null ? "TRUE": xmlDoc.documentElement.getAttribute(attribute);
          
           var newCell = jQuery("<td/>" , { 'class': 'ms-vb2' });
           var newCheckbox =  jQuery("<input "+convertirTextToChecked(currentAttributeArray[attribute])+" type='checkbox' id='"+oField.get_id().toString()+"' schemaattribute='"+attribute+"'/>").click(function(){
          checkboxChange(this.id,this.getAttribute('schemaattribute'),this.checked);
          });
          newCell.append(newCheckbox);
    newRow.append(newCell);
   }

             
    newRow.appendTo("#columnsTableBody");
        
        }
    }      
}

function onQueryFailed(sender, args) {
    alert('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}
function onUpdateSucceeded() {

     SP.UI.Notify.removeNotification(this.fieldUpdateNotifyId);
}

function clearColumnsTable() {

  jQuery("#columnsTableBody").empty();

}


function checkboxChange(fieldId,schemaattribute,value) {
 
 var xmlDoc = this.fieldArray[fieldId]["xmldoc"];
 xmlDoc.documentElement.setAttribute(schemaattribute,value.toString().toUpperCase());
  xmlDoc.documentElement.removeAttribute("Version");
 this.fieldArray[fieldId]["xmldoc"] = xmlDoc;
 
 var oField = this.fieldArray[fieldId]["SPObject"];
 
 if(xmlDoc.documentElement.outerHTML) {
    oField.set_schemaXml(xmlDoc.documentElement.outerHTML);  // Most browsers
 } else {
     oField.set_schemaXml(xmlDoc.documentElement.xml);  // IE
 }
 
    oField.update();
   this.fieldArray[fieldId]["SPObject"] = oField;
      
 clientContext.executeQueryAsync(Function.createDelegate(this, this.onUpdateSucceeded), Function.createDelegate(this, this.onUpdateFailed));
    this.fieldUpdateNotifyId = SP.UI.Notify.addNotification("Actualizando columna",true);
            
}
function convertirTextToChecked(text) {
  if(text == "TRUE" || text == "true") {
   return "checked='checked'";
  }
  else {
   return "";
  }
}
function onUpdateFailed(sender, args) {
 SP.UI.Notify.removeNotification(this.fieldUpdateNotifyId);
    alert('Update failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}

function parseSchemaXml(txt) {
 var xmlDoc = null;
if (window.DOMParser)
  {
  parser=new DOMParser();
  xmlDoc=parser.parseFromString(txt,"text/xml");
  }
else // Internet Explorer
  {
  xmlDoc=new ActiveXObject("msxml2.DOMDocument.6.0");
  xmlDoc.async=false;
  xmlDoc.loadXML(txt);
  } 
  return xmlDoc;
}
</script>
<div>
Lista:<select id="listMenu" onchange="changeList(this)"></select>
</div>
<table id="columnsTable">
<thead>
<tr><td colSpan='6'>Visible en</td></tr>
<tr class="ms-vh2"><td>Columna (nombreInterna)</td>
<td>Display Form</td>
<td>New Form</td>
<td>Edit Form</td>
<td>List Settings</td>
<td>Version History</td>
<td>View Forms</td>
<tbody id="columnsTableBody">
</tbody>
</table>