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
<span style="display:none;" id="el_
_
">
</span>
<script type="text/javascript">
$(function()
{ var mySpan = $('#el_
_
');
var myShortText = $(mySpan).text().substring(0, 20);
if ($(mySpan).text().length > 20)
myShortText += '...';
$(mySpan).show().html(myShortText); });
</script>
Notes
- If you prefer to not escape the brackets you can use CDATA tags: hello]]>
- 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 :)
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
]]>
]]>
Sample 2: Title with ECB
-
Sample 3: Random formatting
]]>
]]>
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 !