Advanced Computed Field - updated with XSL


March 2, 2012 - 08:28, by Steven Van de Craen - 4 Comments

Yesterday I updated the download and source code for the Advanced Computed Field at the Ventigrate Public Code Repository with an XSL stylesheet. This was needed to fix an issue with the field not rendering values when filtered through a Web Part Connection.

The Advanced Computed Field relies on CAML to have the most flexibility of formatting, since SharePoint 2010 introduces XSL based Fields I updated it with the CAMLRendering=”TRUE” flag. This seemed to work for everything except an issue reported by Federico Sanchez regarding Connected Web Parts.

Federico came with the solution to the problem by adding the XSL stylesheet (nothing else needed to be changed), so it really is a nice solution.

<?xml version="1.0" encoding="utf-8" ?> <xsl:stylesheet xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal"> <xsl:template match="FieldRef[@FieldType='AdvancedComputedField']" mode="Computed_body"> <xsl:param name="thisNode" select="."/> <xsl:value-of select="ddwrt:HtmlDecode($thisNode/@*[name()=current()/@Name])" disable-output-escaping="yes"/> </xsl:template> </xsl:stylesheet>

Solution upgrade

If you’re using the Advanced Computed Field in SharePoint 2010, it is advised to update the Solution Package (WSP) to the latest version (available in the download). It won’t break the existing use.

Download: link


ACF 2010: Announcing the Advanced Computed Field for SharePoint 2010


May 26, 2011 - 16:07, by Steven Van de Craen - 1 Comments

Finally available: the SharePoint 2010 version of the Advanced Computed Field. Don’t know what it is ? Check this out:

http://ventigrate.codeplex.com/wikipage?title=Advanced%20Computed%20Field

ACF2010

(the Advanced Computed Field rendering a highlighted/italic item title)


Conditional Formatting using the Advanced Computed Field


November 7, 2009 - 11:31, by Steven Van de Craen - 2 Comments

I got a question on how to use the Advanced Computed Field for conditional formatting and when I finished writing up the response I figured I might as well share it with the community, being you all :)

Here’s the config I used:

<FieldRefs>
<FieldRef Name="TestField" /> </FieldRefs> <DisplayPattern>

<Switch> <Expr>
    <Field Name="TestField" /> </Expr>
   <Case Value="value1">
     <HTML><![CDATA[<div style='color: green;'><b>GREEN</b></div>]]></HTML> </Case> <Case Value="value2"> <HTML><![CDATA[<div style='color: blue;'><b>BLUE</b></div>]]></HTML> </Case> <Case Value="value3"> <HTML><![CDATA[<div style='color: red;'><b>RED</b></div>]]></HTML>
  </Case>
   <Default> <HTML><![CDATA[<div style='color: brown;'><b>BROWN</b></div>]]></HTML> </Default>
</Switch> </DisplayPattern>


Ellipsis on list item body using jQuery


October 1, 2009 - 22:35, by Steven Van de Craen - 0 Comments

A common question to receive is on list items with a long body (eg. Announcements) and then show only X characters and optionally a ‘read more’ link. Many ways to solve this but I went for the following: a Custom Field Type that renders the short text with ellipsis using jQuery.

This is another example using the Advanced Computed Field in a creative way. The ACF allows you to create computed fields referencing other fields or data in your list and manipulating them through CAML or JavaScript. It has the advantage that this can be done from within the browser, however I admit CAML isn’t the easiest of things to comprehend in the SharePoint technology stack.

Ellipsis sample

This ellipsis displays the first 20 characters of the plain text version of the Announcement Body

<FieldRefs> 
     <FieldRef Name="Body" />
     <FieldRef Name="ID" />
</FieldRefs>

<DisplayPattern>
     <HTML>&lt;span style="display:none;" id="el_</HTML>
     <GetVar Name="WPQ" />
     <HTML>_</HTML>
     <Field Name="ID" />
     <HTML>"&gt;</HTML>
     <Field Name="Body" />
     <HTML>&lt;/span&gt;</HTML>
     <HTML>
     &lt;script type="text/javascript"&gt;
     $(function()
     { var mySpan = $('#el_</HTML>
     <GetVar Name="WPQ" />
     <HTML>_</HTML>
     <Field Name="ID" />
     <HTML>');
       var myShortText = $(mySpan).text().substring(0, 20); 
       if ($(mySpan).text().length &gt; 20)
         myShortText += '...';

       $(mySpan).show().html(myShortText); });
     &lt;/script&gt;</HTML>
</DisplayPattern>

Notes
  • If you prefer to not escape the brackets you can use CDATA tags: <HTML><![CDATA[<b>hello</b>]]></HTML>
  • GetVar ‘WPQ’ returns the unique Web Part ID. This takes care of multiple List View Web Parts on the same page
  • You could optimize the output by extracting most of the script and placing it in an externally referenced JavaScript file
  • My JavaScript/jQuery skills aren’t the best. I’ll have to ask Jan for some jQuery pointers next time :)


Advanced Computed Field


March 31, 2009 - 21:34, by Steven Van de Craen - 31 Comments

Introduction

This project originally started as ‘TitleLinkField’ because I needed a way to display the Title field as a hyperlink to the document in a document library, but it ended up being more than just that so I chose a more generic name for it.

I had some experience with Custom Field Types but event then I spent too many hours (even days) on figuring this one out. It started with standard functionality such as Calculated Field and Computed Field, both having their flaws and limitations. I quickly realised that Custom Field Types might be the only way to tackle the scenario at hand.

Use

When creating a field based on this type (“Advanced Computed Field”) you need to provide two properties; FieldRefs (MSDN FieldRefs Element (List)) and DisplayPattern (MSDN: DisplayPattern Element (List)). The former requires a list of referenced fields that exist in the collection of our field while the latter contains CAML used for displaying our field. See the MSDN pages on both elements for the schema and possible values.

What better way than demonstrating by showing ?

Sample 1: Title linked to document

<FieldRefs>
     <FieldRef Name="ServerUrl" />
     <FieldRef Name="Title" />
</FieldRefs>

<DisplayPattern>
     <HTML><![CDATA[<a href="]]></HTML>
     <Field Name="ServerUrl" />
     <HTML><![CDATA[" title="]]></HTML>
     <Field Name="ServerUrl" />
     <HTML><![CDATA[">]]></HTML>
     <Field Name="Title" />
     <HTML><![CDATA[</a>]]></HTML>
</DisplayPattern>

Sample 2: Title with ECB

<FieldRefs>
     <FieldRef Name="Title" />
     <FieldRef Name="_EditMenuTableStart" />
     <FieldRef Name="_EditMenuTableEnd" />
</FieldRefs>

<DisplayPattern>
     <FieldSwitch>
         <Expr>
              <GetVar Name="FreeForm" />
          </Expr>
          <Case Value="TRUE">
               <HTML>-</HTML>
          </Case>
          <Default>
               <Field Name="_EditMenuTableStart" />
               <SetVar Name="ShowAccessibleIcon" Value="1" />
               <Field Name="Title" />
               <SetVar Name="ShowAccessibleIcon" Value="0" />
               <Field Name="_EditMenuTableEnd" />
          </Default>
     </FieldSwitch>
</DisplayPattern>

Sample 3: Random formatting

<FieldRefs>
     <FieldRef Name="MyChoiceField" />
</FieldRefs>

<DisplayPattern>
     <HTML><![CDATA[<span style="background-color: red;">]]></HTML>
     <Field Name="MyChoiceField" />
     <HTML><![CDATA[</span><input type="button" value="Click me" />]]></HTML>
</DisplayPattern>

You can learn a lot by examining the default fields in a document library or list. A tool such as Stramit SharePoint 2007 Caml Viewer is invaluable here.

Technical

A Custom Field Types derives from a parent class (MSDN: Custom Field Classes). Furthermore you have to define the ParentType field declaratively in the FieldTypes XML definition. It is advised (maybe even required) for them to be the same type.

Choose the ‘parent class’ that most closely matches your requirements. If you need a ‘text field with regular expression validation’ then go for SPFieldText because that has a lot of textbox relation functionality (especially on the New, Edit and Display Forms).

The ‘ParentType’ field seems to be the key for CAML related functionality (such as the AllItems View). In my case setting it to “Text” meant that my field didn’t retrieve the values of the referenced fields so it needed to be “Computed”.

The main issues with the standard Computed Field is that it is invisible from any view; Site Columns, Field in a Content Type, etc. and can only be created declaratively via XML/CAML or through code. Other than these issues the Computed Field did exactly what was needed; render columns in a way that I wanted via the RenderPattern. It turns out that the visibility of a Custom Field Type can be controlled in the declarative XML via the ”ShowOn…” fields.

For storing and retrieving the DisplayPattern and FieldRefs properties my custom field type exposes two methods that make calls to internal SharePoint methods:

public void SetInnerXmlForNode(string nodeName, string innerXml)
{
     Type fldType = this.GetType();
     XmlDocument doc = new XmlDocument();
     doc.LoadXml(String.Format("<{0}>{1}</{0}>", nodeName, innerXml));

     MethodInfo miSetXml = fldType.GetMethod("SetInnerXmlForNode", BindingFlags.Instance | BindingFlags.NonPublic);
     miSetXml.Invoke(this, new object[] { nodeName, doc.DocumentElement.InnerXml });
}

public string GetInnerXmlForNode(string nodeName)
{
     string result = null;
     Type fldType = this.GetType();

     MethodInfo miGetXml = fldType.GetMethod("GetNodeFromXmlDom", BindingFlags.Instance | BindingFlags.NonPublic);
     XmlNode resultNode = miGetXml.Invoke(this, new object[] { nodeName }) as XmlNode;
     if (resultNode != null)
     {
          StringBuilder sb = new StringBuilder();
          XmlWriterSettings settings = new XmlWriterSettings();
          settings.Indent = true;
          settings.ConformanceLevel = ConformanceLevel.Fragment;
          using (XmlWriter writer = XmlTextWriter.Create(sb, settings))
          {
               resultNode.WriteContentTo(writer);
          }

          result = sb.ToString();
     }
     return result;
}

Download and installation

If you’re interested in reusing or modifying the code feel free to do so. If you just want this installed and available on your SharePoint farm then go for the WSP and deploy via STSADM.

STSADM -o addsolution -filename VNTG.CustomFieldTypes.AdvancedComputedField.wsp
STSADM -o deploysolution -name VNTG.CustomFieldTypes.AdvancedComputedField.wsp -allowgacdeployment -immediate -allcontenturls

Word of caution

There isn’t a lot of validation on the input of the XML properties. It has to be valid XML but that’s about it. Please follow the schema for FieldRefs and DisplayPattern to make sure you don’t break other functionality. It cannot ‘bring down the farm’ or anything, but it could definitely mess up the rendering of the View.

Have fun with it !