Creating or customizing Field Types

Customizing SPS is sometimes a hassle. I'm not talking about customizing graphics or Frontpaging the pages into submission - I'm talking about extending the object model. Creating new templates for sites and lists, and so on. It's a hassle, which is why I'm always happy when things work out the way I expect them to. :)

On today's menu - adding a new Custom Field Type to the Sharepoint list repertoire.
This came out a bit longer than I expected, but I'm sure you'll pull through.

 

Question One: Why?

 

Sharepoint comes with a wide variety of field types. Text, of course, and others - URLs and Choice fields and Calculated columns and so on. Each has its own representation in the DB, and each has its own rendering pattern - how it is rendered into HTML when you view a View or a Form.
Sometimes we want to create a new type of data to put in our fields. Let's say we have a document management system, and we access out documents using the following URL: http://docserver/getdocument.aspx?docid=xxx. Let's say we want to be able to add to an item in a Discussion list a new field containing a document link. It'd be a shame to make it a URL field and make the users always type out the first, static part of the URL when all they want to write is the document ID.
Our example field will be a DocumentID field which automatically renders as a link to the document management system.

 

Question Two: How?

 

Step one: Creating the Field Type

Field types are defined in the FLDTYPES.XML set in the C:\Program Files\Common Files\Microsoft Shared\web server extensions\60\TEMPLATE\lcid\XML directory. (1033 is the default English installation. 1037 is the Hebrew locale ID).

This rather large (~300KB for a new installation) contains the definitions of all the field types, in a rather plain schema:

<Row>

    <Field Name="TypeName" DisplayName="TypeName">Text</Field>

    <Field Name="InternalType" DisplayName="InternalType">Text</Field>

    <Field Name="SQLType" DisplayName="SQLType">nvarchar</Field>

    <Field Name="Sortable" DisplayName="Sortable">TRUE</Field>

    <Field Name="Filterable" DisplayName="Filterable">TRUE</Field>

<RenderPattern Name="HeaderPattern" DisplayName="HeaderPattern" />

<RenderPattern Name="DisplayPattern" DisplayName="DisplayPattern">

<RenderPattern Name="EditPattern" DisplayName="EditPattern" />

</Row>

 

The Fields contain the basic information about the type:

TypeName is the name we give our new type, to be used later.

InternalType is the basic type that our type extends. Consider it a Base class.

SQLType is the SQL datatype that is used to persist our field data to the SQL store.

Sortable and Filterable – rather self explanatory.

 

After these fields come several RenderPatterns (there are more which I cropped for brevity).

These Patterns are rendering instructions – in CAML notation – that instruct SPS how to translate our field and the data within to HTML in each situation. The DisplayPattern, for instance, is how the data is rendered when the field is displayed normally – in a grid in the AllItems.aspx view, or as part of the Item Details screen in DispForm.aspx.

 

For our DocumentID field, we will first change the TypeName of  the type:

<Field Name="TypeName" DisplayName="TypeName">DocumentID</Field>

 

To keep things simple, we will keep the current EditPattern as it is (a simple textbox) and change the DisplayPattern only.

Originally, we have this:

 

<RenderPattern Name="DisplayPattern" DisplayName="DisplayPattern">

  <Column HTMLEncode="TRUE" AutoHyperLink="TRUE" AutoNewLine="TRUE" />

  </RenderPattern>

 

A simple pattern – the Column tag rendered directly.

From the SDK: " The Column element is used to return the raw data value for a particular field". In our case – return the raw data saved in the SQL server. The text is automatically HTMLEncoded and its prefix checked for common protocol names (http://, ftp://, etc) and if found, automatically rendered as a hyperlink.

What we'll want to do is remove the AutoHyperlink, and have the data automatically wrapped in a <a href> that is prefixed with the URL to the document management server:

 

<RenderPattern Name="DisplayPattern" DisplayName="DisplayPattern">

  <HTML><![CDATA[<a href="http://docserver/getdoc.aspx?docid=]]></HTML>

  <Column HTMLEncode="TRUE" AutoHyperLink="FALSE" AutoNewLine="TRUE/>

   <HTML><![CDATA[">]]></HTML>

  <Column HTMLEncode="TRUE" AutoHyperLink="FALSE" AutoNewLine="TRUE/>

   <HTML><![CDATA[</a>]]></HTML>

  </RenderPattern>

 

 

(I've tried to color-code the mess a bit. Dark red is for CAML tags. Blue is for the CDATA blocks, and black is the actual HTML that is rendered.

What we have here is an HTML block which writes out <a href=", then the <Column> tag, then a closing bracket. This will form the following HTML:
<a href="http://docserver/getdoc.aspx?docid=my column data">

The second <Column> tag writes the data again, then we close the link. Final rendered output:

<a href="linktodoc">DocumentID</a>

 

Notes:

  • The CDATA blocks are there to allow us to write straight HTML without having to escape each and every < and >. They do add to the mess, though.
  • Remember that CAML's boolean values should always be capitalized. "TRUE", not "True".

 

Step Two: Creating a derived field.

 

Let's go to the standard SPS Topic area definition – SPSTOPIC, as defined in C:\Program Files\Common Files\Microsoft Shared\web server extensions\60\TEMPLATE\lcid\SPSTOPIC.

Specifically, we will edit the SCHEMA.XML file for the Discussion board list template – under the LISTS\DISCUSS subdirectory.

 

The SCHEMA.XML is also rather lengthy – it contains the definition for all the Views for this list. We will concentrate on only one area, though.

Right at the top we have the List -> MetaData -> Fields node. It's initially empty (having only the basic fields inherited from the Base Type), but we will add a new one:

<Field Name="DocLink" Type="DocumentID" DisplayName="Link To Document">

</Field>

 

This will add the DocLink field to all lists based on the DISCUSS list template. Now, when we add a new item to such a list, we'll see a "Link To Document" field – rendered as a simple textbox. We'll write our Document ID in this field, and save the item.

When we open the item to view its properties, we'll see our DocumentID in all its glory – rendered as a link to our document management system.

 

Don't forget that the new field will not automatically be added to the All Items view – we'll have to add it manually, either via the Manage List page or directly in the SCHEMA.XML file.

 

Good luck.

7 Comments

  • Eric_Formark said

    Cool, now I know what that element is! Do you know if there's a schema for CAML? I'd like to learn what other elements I can use in a DisplayPattern.

  • Adil Hussain said

    I am sure this is the right place to ask this question but i am desperate to ask a question which is, I want to customize CAML query in a way that whatever data it is returning i want to add a new column which will be created on the fly and not in the original list. Like, there are two columns, FirstName and LastName, i want to retrun one more column FullName which will concatenate the FirstName and LastName columns and return it. Like we do in SQL query, any help will be greatly appreciated. Thanks

  • best ipad stand said

    ----------------------------------------------------------- "I happen to be studying your entries during my afternoon break, and i need to admit the entire write-up has been very enlightening and very effectively composed. I believed I'd let you know that for some cause this weblog doesn't show properly in World wide web Explorer eight. I wish Microsoft would quit changing their software program. I've a query for you. Do you mind exchanging blog roll links? That could be actually cool! "

Comments have been disabled for this content.