Custom CAML Views in SharePoint Team Services

 

Microsoft Corporation

June 2002

Applies to:
   SharePoint™ Team Services from Microsoft

Summary: Learn to create custom views of list data within Microsoft SharePoint Team Services using the View element in Collaborative Application Markup Language (CAML). (20 printed pages)

Contents

Introduction
Creating a Basic List View
Using a View Within Script
Adding Personalized Messages
Listing All the Subwebs on the Server
Prepopulating Input Boxes
Embedding Views Within Views
Creating Thumbnails

Introduction

The View element of Collaborative Application Markup Language (CAML) provides a flexible means for performing queries and returning values from the database in SharePoint™ Team Services from Microsoft®. This element answers a broad range of needs for customizing SharePoint team Web sites, from performing queries in order to return data to script functions for processing, to laying out the display of list data in the <BODY> section of a page.

Important   You must have the Write Pages permission to upload pages. You must be logged on to the server computer as a member of the local Administrators group to write to the database.

Typical schemas for list views on the team Web site's Default.htm page or on any list's AllItems.htm page contain the following subelements, depending on whether your aim is to both return and display values, or to just return values for processing in script.

**Query   **This subelement can be empty if you simply want to return all values in a list.

**ViewBody  ** The ViewBody subelement can be used with or without the ViewHeader and ViewFooter elements to lay out a view table for displaying data.

**ViewEmpty   **The ViewEmpty subelement specifies what to display if no data is returned from the query. It also provides useful conditionality for executing an alternative view in case no items are returned from a query. See examples below.

**ViewFields   **The ViewFields subelement can be empty when the view is not being used to display items but only to return values for processing,

**RowLimit   **The RowLimit subelement specifies the number of items to display in the current window.

**PagedRowset   **The PagedRowset subelement defines a view for the next window when the value contained by the RowLimit element is exceeded.

**Toolbar   **On an AllItems.htm page, the Toolbar subelement defines the buttons and section line that appear on the page directly above the list view.

Use the CAML HTML element with a CDATA marker to embed markup language or script within a view (for example, <HTML><![CDATA[<TABLE><TR><TH>]]></HTML>).

**Important   **In order to complete the task described below you must have the Write Pages permission to upload pages. You must be logged on to the computer as a member of the local Administrators group to write to the database.

Assuming you have access to the SharePoint Team Services database, you can study and customize views by copying the view schema from the View column of the Views table. For many views, you can identify the appropriate database record through the globally unique identifier (GUID) of the ListView component that you want to modify. In other cases, such as in forms, you may need to refer to a combination of ID, Name, or Title column values in the Lists table (the list of lists). You can then replace the entire component with its view schema, surrounding the copied view with the following CAML:

<ows:XML>
  <SetList>[u_YourCustomListName[without "u_" for native lists]]</SetList>
  <View>
    .
    .
    .
    [Copied view schema goes here]
    .
    .
    . 
  </View>
</ows:XML>

In Microsoft FrontPage®, you can select a view, right-click the view, and click Layout Customization to expand the view schema and make customizations.

Note   Always save a copy of the original site page so that you can always recuperate the component if needed.

Creating a Basic List View

The following example lays out a view table for displaying a custom list (u_MyCustomList). The ViewFields element specifies that the Title, Stock, and Price field names be displayed in the view's header and that the values for these fields be displayed in the view's body.

<ows:XML>
  <SetList>[u_MyCustomList]</SetList>
  <View Name="MyNewView">

    <ViewFields>
      <FieldRef Name="Title"/>
      <FieldRef Name="Stock"/>
      <FieldRef Name="Price"/>
    </ViewFields>

The ViewHeader element contains Fields and Field elements that enumerate the field names specified by the ViewFields element. HTML elements contain the markup language for displaying table headers according to the ms-vh style defined in the /_layouts/styles/ows.css file of the Web or subweb.

    <ViewHeader>
      <HTML><![CDATA[<TABLE><TR class="ms-vh">]]></HTML>
      <Fields>
        <HTML><![CDATA[<TH>]]></HTML>
        <Field/>
        <HTML><![CDATA[</TH>]]></HTML>
      </Fields>
      <HTML><![CDATA[</TR>]]></HTML>
    </ViewHeader>

The ViewBody element contains Fields and Field elements that enumerate the field values for each item in the list. HTML elements contain the markup language for displaying these values in table cells according to the ms-vb style defined in the /_layouts/styles/ows.css file for the Web or subweb.

    <ViewBody>
      <HTML><![CDATA[<TR class="ms-vb">]]></HTML>
        <Fields>
          <HTML><![CDATA[<TD>]]></HTML>
          <Field/>
          <HTML><![CDATA[</TD>]]></HTML>
        </Fields>
      <HTML><![CDATA[</TR>]]></HTML>
    </ViewBody>

    <ViewFooter>
      <HTML><![CDATA[</TABLE>]]></HTML>
    </ViewFooter>

The Query section queries for cases where stock is less than 15 or price is greater than 20.00.

    <Query>
      <Where>
        <Or>
          <Lt>
            <FieldRef Name="Stock"/>
            <Value Type="Number">
              15
            </Value>
          </Lt>
          <Gt>
            <FieldRef Name="Price"/>
            <Value Type="Currency">
              20.00
            </Value>
          </Gt>
        </Or>
      </Where>
      <OrderBy>
        <FieldRef Name="Title"/>
      </OrderBy>
    </Query>
  </View>
</ows:XML>

To return all values for the specified fields, you can use an empty Query element (<Query/>) instead.

Using a View Within Script

The next example illustrates how to use a CAML view to return item IDs and assign them to an array for processing within script. The view returns a comma-delimited list of IDs for items in which the event date is greater than 1/1/2002. The item IDs are assigned to the strIDs variable and then displayed one by one in a message box.

<Script language="JavaScript">
function getIDs()
{
   var arrIDs = new Array();
   var strIDs="<ows:XML>
             <SetList>Events</SetList>
             <View>
               <ViewFields>
                 <FieldRef Name="ID"/>
               </ViewFields>
               <ViewBody>
                 <Fields>
                   <Field/>
                   <HTML><![CDATA[,]]></HTML>
                 </Fields>
               </ViewBody>
               <Query>
                 <Where>
                     <Gt>
                       <FieldRef Name="EventDate"/>
                       <Value Type="DateTime">2002-01-01T00:00:00Z</Value>
                     </Gt>
                 </Where>
               </Query>
             </View>
           </ows:XML>";

   arrIDs=strIDs.split(/,/);
   alert(arrIDs);
}
</Script>

Note   If you want to dynamically insert user-entered data in a CAML view, instead of merely hard-coding a value as in the above example, you need to disguise the CAML from the interpreter to prevent immediate processing of the view. For more information, see Using XMLHTTP to Post Commands in SharePoint Team Services.

Adding Personalized Messages

To get the current user's name and display a personalized message, the following code sample performs a query on the UserInfo table, the global list in the database that contains all user information for all team Web sites on a virtual server.

<ows:XML>
  <SetList>UserInfo</SetList>
  <View>
    <ViewFields>
      <FieldRef Name="Title"/>
    </ViewFields>
    <Query>
      <Where>
        <Eq>
          <FieldRef Name="ID"/>
          <Value Type="Integer"><UserID/></Value>
        </Eq>
      </Where>
    </Query>
    <ViewBody>
      <HTML>
        <![CDATA[<TABLE><TR><TD class="Greeting">Hello ]]>
      </HTML>
      <Field Name="Title"/>
      <HTML>
        <![CDATA[, welcome to the team Web site.</TD></TR></TABLE>]]>
      </HTML>
    </ViewBody>
  </View>
</ows:XML>

The sample queries for cases where the current user's ID matches an ID in the UserInfo table and displays the corresponding Title field value (in this case, the user's name) as specified by the ViewFields element. The CDATA sections lay out a simple table for alignment of a personalized greeting on the page. Note that, for formatting, custom style definitions can be added to ows.css and implemented within the HTML <TABLE> and its elements.

Listing All the Subwebs on the Server

The following sample shows how to create a view that returns a list of links to all the subwebs on the server by creating a view on the Projects table in the database:

<ows:XML>
  <SetList>Projects</SetList>
  <View Name="ProjectsView">
    <ViewFields>
      <FieldRef Name="Title"/>
      <FieldRef Name="HomePageID" Explicit="TRUE"/>
    </ViewFields>
    <ViewHeader>
    <HTML><![CDATA[<TABLE>]]></HTML>
    </ViewHeader>
    <ViewBody>
     <HTML><![CDATA[<TR><TD>]]></HTML>
       <HTML><![CDATA[<a target="_blank" href="]]></HTML>
       <LookupColumn Name="HomePageID"/>
       <HTML><![CDATA[">]]></HTML>
       <Field Name="Title"/>
       <HTML><![CDATA[</a></TD></TR>]]></HTML>
    </ViewBody>
    <ViewFooter>
    <HTML><![CDATA[</TABLE>]]></HTML>
    </ViewFooter>
  </View>
</ows:XML>

The HomePageID field is a lookup field to the DocMd table, which stores all the URLs on the server. Here, the HTML target attribute is set to _blank so that when a user clicks a subweb link, that subweb is displayed in a new window.

Prepopulating Input Boxes

To prepopulate a form with the current user's name and e-mail address, you can create a view that returns the user's name and then assign it to a variable. Use the GetEmailFromUser element to return the current user's e-mail address.

First add a CAML island defining the view to the page that contains the form (This code example's lines have been "broken" to fit within MSDN Web layout requirements):

<ows:XML>
  <SetList>UserInfo</SetList>
  <View>
    <ViewFields>
      <FieldRef Name="Name"/>
    </ViewFields>
      <Query>
        <Where>
          <Eq>
            <FieldRef Name="ID"/>
            <Value Type="Integer"><UserID/></Value>
          </Eq>
        </Where>
      </Query>
      <ViewBody>
          <SetVar Name="UName" Scope="Request"><Field 
Name="Name"/></SetVar>
      </ViewBody>
    </View>
</ows:XML>

Notice that the view is only used to return the current user's name, which is assigned to a custom CAML variable UName.

You can then add two input boxes and assign the appropriate CAML to their value attributes:

<input type="text" name="username" size="38" value="<ows:GetVar Name="UName"/>">

<input type="text" name="user_email" size="38" value="<ows:GetEmailFromUser HTMLEncode="TRUE"><UserID/></ows:GetEmailFromUser>">

Embedding Views within Views

Views can be embedded within other views to return values from more than one table in the SharePoint Team Services database. In the example below, two views are embedded within another framing view on the home page to display a different message to the current user, depending on whether that user has overdue tasks.

The example involves two views of the Tasks list, one for returning a message with a particular formatting in case the current user has overdue tasks, and another for returning a view of the overdue items.

<ows:XML>
  <SetList>Tasks</SetList>
  <View>
    <ViewFields>
      <FieldRef Name="AssignedTo"/>
    </ViewFields>
    <Query>
      <Where>
        <And>
          <Eq>
            <FieldRef Name="AssignedTo"/>
            <Value Type="Integer">
              <UserID/>
            </Value>
          </Eq>
          <And>
            <Lt>
              <FieldRef Name="DueDate"/>
              <Value Type="DateTime">
                <Today/>
              </Value>
            </Lt>
            <Neq>
              <FieldRef Name="Status"/>
              <Value Type="Choice">Completed</Value>
            </Neq>
          </And>
        </And>
      </Where>
    </Query>
    <ViewBody>
      <HTML><![CDATA[<TABLE><TR><TD class="Warning">Hello ]]></HTML>
      <LookupColumn Name="AssignedTo" HTMLEncode="TRUE"/>
      <HTML><![CDATA[, these items are now past due!</TD></TR>
      <TR><TD>
        <A href="mailto:Manager_Name@example.com" class="ResolveNow">
          Please contact your manager</A>
      </TD></TR>
      <TR><TD>]]></HTML>

This framing view queries the Tasks table in the database for cases where the current user's ID equals an AssignedTo field value and where the due date is less than today and the status does not equal Completed. A LookupColumn element is used to return the user's name as part of a personalized warning to the user.

At this point in the code, the other view of the Tasks list can be inserted, which returns and displays the overdue items.

      <SetList>Tasks</SetList>
      <View>
        <ViewFields>
          <FieldRef Name="LinkTitle"/>
          <FieldRef Name="Priority"/>
          <FieldRef Name="Body"/>
          <FieldRef Name="DueDate"/>
        </ViewFields>
        <Query>
          <Where>
            <And>
              <And>
                <Lt>
                  <FieldRef Name="DueDate"/>
                  <Value Type="DateTime">
                    <Today/>
                  </Value>
                </Lt>
                <Neq>
                  <FieldRef Name="Status"/>
                  <Value Type="Choice">Completed</Value>
                </Neq>
              </And>
              <Eq>
                <FieldRef Name="AssignedTo"/>
                <Value Type="Integer">
                  <UserID/>
                </Value>
              </Eq>
            </And>
          </Where>
        </Query>
        <ViewHeader>
          <HTML><![CDATA[<TABLE><TR>]]></HTML>
          <Fields>
            <HTML><![CDATA[<TH class="ms-vh">]]></HTML>
            <Field/>
            <HTML><![CDATA[</TH>]]></HTML>
          </Fields>
          <HTML><![CDATA[</TR>]]></HTML>
        </ViewHeader>
        <ViewBody>
          <HTML><![CDATA[<TR>]]></HTML>
          <Fields>
            <HTML><![CDATA[<TD class="ms-vb">]]></HTML>
            <Field/>
            <HTML><![CDATA[</TD>]]></HTML>
          </Fields>
          <HTML><![CDATA[</TR>]]></HTML>
        </ViewBody>
        <ViewFooter>
          <HTML><![CDATA[</TABLE>]]></HTML>
        </ViewFooter>
      </View>
      <HTML><![CDATA[</TD></TR></TABLE>]]></HTML>
    </ViewBody>

This completes the ViewBody section of the outer, framing view, pertaining to the case where the current user has overdue tasks. The ViewEmpty section can be used to contain another view that conveys a different message to the current user who has no overdue tasks.

    <ViewEmpty>
      <SetList>UserInfo</SetList>
      <View>
        <ViewFields>
          <FieldRef Name="Title"/>
        </ViewFields>
        <Query>
          <Where>
            <Eq>
              <FieldRef Name="ID"/>
              <Value Type="Integer"><UserID/></Value>
            </Eq>
          </Where>
        </Query>
        <ViewBody>
          <HTML>
            <![CDATA[<TABLE><TR><TD class="NoOverdues">Hello ]]>
          </HTML>
          <Field Name="Title"/>
          <HTML><![CDATA[, you have no past due items. Great work!</TD></TR></TABLE>]]></HTML>
        </ViewBody>
      </View>
    </ViewEmpty>
  </View>
</ows:XML>

Styles can be defined for the above attributes by adding definitions to /_layouts/styles/ows.css, such as the following:

.Warning  {
 font-size: 14pt;
 color: red;
 font-weight: bold;
 font-family: verdana;
 }
.ResolveNow  {
 font-size: 12pt;
 color: red;
 text-decoration: underline;
 font-family: verdana;
 padding: 12px;
 font-weight: bold;
 }
.NoOverdues  {
 font-size: 12pt;
 color: green;
 font-family: verdana;
 padding: 12px;
 font-weight: bold;
 }

The next example embeds a view within the ViewEmpty section of a framing view to display a different message to current users who visit a home page, depending on whether they've taken a survey called TeamSurvey. If they have taken the survey, the ViewBody section displays a personalized thank you message. If not, the ViewEmpty section displays a warning and provides a link to the survey (This code sample has had lines "broken" to fit within MSDN Web layout requirements):

<ows:XML>
  <SetList>u_TeamSurvey</SetList>
  <View>
    <ViewFields>
      <FieldRef Name="Author"/>
    </ViewFields>
    <Query>
      <Where>
        <Eq>
          <FieldRef Name="Author"/>
          <Value Type="Integer"><UserID/></Value>
        </Eq>
      </Where>
    </Query>
    <ViewBody>
      <HTML><![CDATA[<TABLE><TR><TD class="DidSurvey">Hello ]]></HTML>
      <LookupColumn Name="Author" HTMLEncode="TRUE"/>
      <HTML><![CDATA[, thanks for taking the 
survey!</TD></TR></TABLE>]]></HTML>
    </ViewBody>
    <ViewEmpty>
      <SetList>UserInfo</SetList>
        <View>
          <ViewFields>
            <FieldRef Name="Title"/>
          </ViewFields>
          <Query>
            <Where>
              <Eq>
                <FieldRef Name="ID"/>
                <Value Type="Integer"><UserID/></Value>
              </Eq>
            </Where>
          </Query>
          <ViewBody>
            <HTML>
              <![CDATA[<TABLE><TR><TD class="Warning">Hello ]]>
            </HTML>
            <Field Name="Title"/>
           <HTML>
             <![CDATA[, you have not yet taken the survey!
               </TD></TR><TR><TD class="TakeNow">
               <A href="http://[server_name]/[subweb_name]/Lists/
                 TeamSurvey/overview.htm">
                 Please take the survey immediately!</A>
               </TD></TR></TABLE>]]></HTML>
          </ViewBody>
        </View>
    </ViewEmpty>
  </View>
</ows:XML>

You can also add appropriate style definitions to ows.css.

.TakeNow  {
 font-size: 12pt;
 color: red;
 text-decoration: underline;
 font-family: verdana;
 padding: 12px;
 font-weight: bold;
 }
.DidSurvey  {
 font-size: 12pt;
 color: green;
 font-family: verdana;
 padding: 12px;
 font-weight: bold;
 }

A more extreme measure can be taken by making the ViewBody section an empty element and simply using the ViewEmpty section to redirect the user to the survey without even letting them see the home page, such as follows:

<ows:XML>
  <SetList>u_TeamSurvey</SetList>
    <View>
      <ViewFields/>
      <Query>
        <Where>
          <Eq>
            <FieldRef Name="Author"/>
            <Value Type="Integer"><UserID/></Value>
          </Eq>
        </Where>
      </Query>
      <ViewBody/>
      <ViewEmpty>
        <SetList>UserInfo</SetList>
          <View>
            <ViewFields/>
            <Query>
              <Where>
                <Eq>
                  <FieldRef Name="ID"/>
                  <Value Type="Integer"><UserID/></Value>
                </Eq>
              </Where>
            </Query>
          <ViewBody>
            <HTML><![CDATA[<Script>window.parent.location =  
              "http://[server_name]/[subweb_name]
              /Lists/TeamSurvey/overview.htm";</Script>]]></HTML>
          </ViewBody>
          </View>
      </ViewEmpty>
    </View>
</ows:XML>

Here, the ViewBody section simply consists of a script block that assigns the survey's URL to window.parent.location.

Creating Thumbnails

You can create thumbnails for a document library that contains images by embedding HTML within CAML. The following example assumes the existence of a gallery named Image Gallery that has an Artist field in addition to the built-in FileRef and Title fields.

<ows:xml>
  <SetList>u_ImageGallery</SetList>
  <HTML><![CDATA[<TABLE>]]></HTML>
  <View Name="Image Gallery">
    <ViewFields>
      <FieldRef Name="FileRef"/>
      <FieldRef Name="Title"/>
      <FieldRef Name="Artist"/>
    </ViewFields>
    <ViewBody>
      <HTML><![CDATA[<tr><td>]]></HTML>
      <HTML><![CDATA[<a href="]]></HTML>
      <HttpHost URLEncodeAsURL="TRUE"/>
      <LookupColumn Name="FileRef"/>
      <HTML><![CDATA["><img src="]]></HTML>
      <HttpHost URLEncodeAsURL="TRUE"/>
      <LookupColumn Name="FileRef"/>
      <HTML><![CDATA[" width=50 height=50></a></td><td>]]></HTML>
      <Field Name="Title"/>
      <HTML><![CDATA[</td><td>]]></HTML>
      <Field Name="Artist"/>
      <HTML><![CDATA[</td></tr>]]></HTML>
    </ViewBody>
  </View>
  <HTML><![CDATA[</TABLE>]]></HTML>
</ows:xml>

The value of the href attribute, which provides the URL for the link to the image file, is constructed with the CAML HttpHost and LookupColumn elements. The LookupColumn element is used to return the lookup value for the list's FileRef field, in other words, the image file's URL that is contained in the DocMd table, which stores all document URLs for all sites on the server. Title and Artist fields are also displayed in the view.

The same view can also be integrated with Vector Markup Language (VML) to create thumbnails. You can use CDATA sections to construct VML rect and imagedata elements for both displaying an image as a thumbnail and for providing a link to the image file.

<ows:XML>
  <SetList Scope="Request">u_ArtDocs</SetList>
  <View Name="ThumbNailView">    
    <ViewFields>
      <FieldRef Name="FileRef"/>
      <FieldRef Name="Title"/>
      <FieldRef Name="Artist"/>
    </ViewFields>
    <ViewHeader>
      <HTML><![CDATA[<TABLE><TR><TD>]]></HTML>
    </ViewHeader>
    <ViewBody>
      <HTML><![CDATA[<TABLE  cellpadding=20><TR><TD>]]></HTML>
      <HTML><![CDATA[<v:rect href="]]></HTML>
      <HttpHost URLEncodeAsURL="TRUE"/>
      <LookupColumn Name="FileRef"/>
      <HTML><![CDATA[" style="HEIGHT: 50px; LEFT: 10px; 
         POSITION:relative; TOP:10px; WIDTH: 50px">
         <v:imagedata src="]]></HTML>
      <HttpHost URLEncodeAsURL="TRUE"/>
      <LookupColumn Name="FileRef"/>
      <HTML><![CDATA["/></v:rect>]]></HTML>
      <HTML><![CDATA[</TD><TD class=ms-vb><BR>]]></HTML>
      <Field Name="Title"/>
      <HTML><![CDATA[<BR>]]></HTML>
      <Field Name="Artist"/>
      <HTML><![CDATA[</TD></TR></TABLE>]]></HTML>
    </ViewBody>
    <ViewFooter>
      <HTML><![CDATA[</TD></TR></TABLE>]]></HTML>
    </ViewFooter>
    <Query/>
  </View>
</ows:XML>

The rect element's href value, which provides the URL for the link to the image file, is constructed with the CAML HttpHost and LookupColumn elements.

The following processing instructions need to be included on the page for VML to function.

<html dir="ltr" xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office">

<STYLE>
v\:* { behavior: url(#default#VML);} 
o\:* { behavior: url(#default#VML);}
</STYLE>

Further reading

For more information about VML, see the MSDN VML Reference.

For more information about CAML, see the CAML reference in the SharePoint Team Services SDK.