1

I'm creating custom field type - lets name it 'MyCustomType'. I need to change its column title in List View. I tried to use xslt-transform in my fldtypes_MyCustomType.xsl with no luck - nothing changes.

I tried the following code:

<xsl:template name="FieldRef_MyCustomType_header" ddwrt:dvt_mode="header" 
              match="FieldRef[@Type='MyCustomType']" mode="header" priority="9">
  <th class="ms-vh-icon" nowrap="nowrap" scope="col" onmouseover="OnChildColumn(this)">
  <xsl:call-template name="dvt_headerfield">
     <xsl:with-param name="fieldname">MyCustomType</xsl:with-param>
     <xsl:with-param name="fieldtitle">This value I want to change</xsl:with-param>
     <xsl:with-param name="displayname">MyCustomType</xsl:with-param>
     <xsl:with-param name="fieldtype">MyCustomType</xsl:with-param>
  </xsl:call-template>
  </th>
</xsl:template>

I copied this code from Sharepoint fldtypes.xsl, 'FieldRef_Attachments_header' template.

Please help me to make it works.

Olga Golubeva
  • 226
  • 1
  • 9
  • have a look into this example: http://sharepoint.stackexchange.com/questions/109277/modify-list-header-utilizing-xsl – Supermode Aug 19 '15 at 01:01
  • This example is cool, but it manipulates with List View of entire List. I need to modify only my filed title, because my field can be added to any list via code or UI. So I can't predict what kind of list will use my field, and what columns there will be. – Olga Golubeva Aug 19 '15 at 05:56

2 Answers2

1

I'd almost forget about this problem, but accidently I'd found the way to solve it.

The main difference between SP2013 and SP2010 - is javascript rendering! In 2013 - javascript is everywhere, and XsltListViewWebParts (classic list view) by default are rendering on client too. That's why Xslt-transformations for header working, but not visible! To see it, go to the List View Page -> "Change Page" -> "Change XsltListViewWebPart properties" -> find checkBox "Render on server" -> Save. XsltListViewWebPart will render at 2010-style and you will see your header from Xslt.

But how to do my custom header in 2013-style, with client render? The answer is - Javascript. You'll have to override javascript header rendering. You can find it in clienttemplates.js

So, full solution is:

  1. When you creating your custom field type, you have to override JS-link for your field:

    public class MyCustomType: SPFieldLookup
    {        
       private const string JSLinkUrl = "~site/_layouts /15/MyCustomType/MyCustomType.js";
    
       public override string JSLink
       {
           get { return JSLinkUrl; }
           set { base.JSLink = value; }
       }
    
      //constructors and other logic
    } 
    

    In file /_layouts /15/MyCustomType/MyCustomType.js you will make all javascript transformations for your field.

  2. Create MyCustomType/MyCustomType.js in the LAYOUTS folder. And there, override renderHeader field of spMgr object:

    (function () {
       spMgr.RenderHeader = function (renderCtx, field) {
            //...
            //you'll have to copy all SPMgr functions from clientTemplates.js 
            //if you want render other fields headers propertly.
            //Simply find string 'function SPMgr() {' and grab this function fully
            //then add you header rendering
            //...
            if (field.Name == 'SelectedFlag')
                return RenderSelectedFlagHeader(renderCtx, field);
            else if (field.Name == 'Checkmark')
                return RenderCheckmarkHeader(renderCtx, field);
            var fieldHeaderRenderMap = {
                Attachments: RenderAttachmentsHeader,
                Computed: RenderComputedHeader,
                CrossProjectLink: RenderCrossProjectLinkHeader,
                Recurrence: RenderRecurrenceHeader,
                DateTime: RenderDateTimeHeader
            };
            var headerRenderer = fieldHeaderRenderMap[field.Type];
    
            if (field.FieldType == 'MyCustomType')
                return RenderMyCustomHeader(renderCtx, field); //this is our rendering!
            else {
                if (headerRenderer != null)
                    return headerRenderer(renderCtx, field);
                return RenderDefaultHeader(renderCtx, field);
            }        
        }
    })(); 
    function RenderMyCustomHeader(renderCtx, field) {
        var iStr = '<th scope="col" onmouseover="OnChildColumn(this)" style="max-width: 500px;" class="ms-vh2" onmousedown="ListHeaderMenu_OnMouseDown(this);">';   
        iStr += "My field -my header from js";
        iStr += '</th>';
        return iStr;
    }
    

Unfortunately, I hadn't find the solution without full overriding SPMgr function from clienttemplates.js. If someone will find it - please add it here!

Update:

And here is the correct XSLT-rendering (fldtypes_MyCustomType.xsl) for Server-side rendering in SP2010-style:

  <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" >
      <xsl:output method="html" indent="no"/>

      <xsl:template name="FieldRef_MyCustomType_header" 
                    match="FieldRef[@FieldType='MyCustomType']" 
                    ddwrt:dvt_mode="header" mode="header" priority="9">
        <th class="ms-vh-icon" nowrap="nowrap" scope="col" onmouseover="OnChildColumn(this)">
          <xsl:attribute name="class">ms-vh2</xsl:attribute>
          <xsl:call-template name="dvt_headerfield">
            <xsl:with-param name="fieldname"><xsl:value-of select="@Name"/>
            </xsl:with-param>
            <xsl:with-param name="fieldtitle">
              MyCustomType from XSL 
            </xsl:with-param>
            <xsl:with-param name="displayname"><xsl:value-of select="@DisplayName"/></xsl:with-param>
            <xsl:with-param name="fieldtype">x:string</xsl:with-param>
          </xsl:call-template>
        </th>
      </xsl:template>

Olga Golubeva
  • 226
  • 1
  • 9
0
<xsl:call-template name="dvt_headerfield">

I think you have a typo, it should be dvt.headerfield. Although I did see posts using the underscore, more authoritative posts like this one uses the dot.

You also write "nothing happens", are you positive that the template FieldRef_MyCustomType_header is ever called? you can check this by adding something like:

<xsl:comment>Hey, I hit my template!</xsl:comment>

at the top of the template, and then check the output.

Abel
  • 101
  • 2
  • Not, it's not a typo. First, I've copied this piece of code from 15\TEMPLATE\LAYOUTS\XSL\fldtypes.xsl, from template FieldRef_Attachments_header. Second, If I use dvt.headerfield - I get an error 'could not load webpart' in list view. Also, my template is never called. – Olga Golubeva Sep 14 '15 at 07:23
  • @OlgaGolubeva, so you have the choice between template never called, and template name raising an error. You should search for what calls FieldRef_MyCustomType_header (if that is indeed currently not called), and analyze your way back step by step. – Abel Sep 14 '15 at 07:35