While SharePoint offers great flexibility to users for quickly creating custom lists in various forms, flexibility of forms and fields rendered within is fairly limited on WSS/MOSS UI. In this series, I aim to share some of my findings and, perhaps, come up with wish-list for "SharePoint 2009"!
There are various types of form customization that we often need to make. For example:
- Show/Hide specific Fields on a form type.
- Show field in read-only mode on Edit form. Not allowing user to edit once field is populated while creating item.
- Allow dynamic behavior for a form regarding above, based on users credentials/rights.
- When a field is read-only, allowing user to override by clicking a link and letting him enter value.
1. Show/Hide a Field
When using content-types, a user can choose to show/hide a field from forms on content-type edit page. When creating custom solutions, or with list definitions, one can decide with following attributes in Field element to show/hide a form field in New, Edit, or Display form. Same can either be done declaratively in your element xml, or through object model updates to list/field schema. In case you are stuck in a environment where you do not have privilege of making custom deployments, and do have access to your site via web-services then you can use Lists.asmx service to send updates to an existing list schema. Following are 6 example options:
<Field ... ShowInDisplayForm = "TRUE" | "FALSE" ShowInEditForm = "TRUE" | "FALSE" ShowInNewForm = "TRUE" | "FALSE" .../>
<FieldRef ... ShowInDisplayForm="TRUE" | "FALSE" ShowInEditForm="TRUE" | "FALSE" ShowInNewForm="TRUE" | "FALSE"></FieldRef>
instance.ShowInEditForm = value;
Using SharePoint Designer:
You can copy existing form-pages and create new one. Remove existing form web-part and create a new ListForm web-part, with flexibility of showing/hiding fields of choice. Be mindful of not unghosting your pages, for the sake of long term hygiene of your site and forms. Details of steps can be browsed here, and here.
Custom Rendering Template
Apart from above, there is a hidden gem in CONTROLTEMPLATES folder, DefaultTemplates.ascx. All of SharePoint forms, be it lists or libraries, are rendered based on RenderingTemplate's that reside in this folder. So if you open the file, you'll notice there is plethora of templates there. Good thing is that we do not need to replace the markup in system files, and they can instead be overridden by creating your own ASCX file and placing the same rendering template (with same ID) in yours. At execution time, your will be preferred and hence will override any system functionality. Having said that, we are interested in a RenderingTemplate named ListForm. This template is responsible for all your list forms (New/Edit/Display). Within the template you'll notice a control ListFieldIterator, which is responsible for iterating through all field at runtime and has a method in its class IsFieldExcluded() which we can use to decide which fields to show on which form at runtime. In the sample below, I'm showing replacement of system control with custom one, <eJugnoo:FormFieldIterator/>:
<%@ Register TagPrefix="eJugnoo" Assembly="eJugnoo.SharePoint, Version=126.96.36.199, Culture=neutral, PublicKeyToken=b5eacb14abbc6805" namespace="eJugnoo.SharePoint.FormSettings" %> <SharePoint:RenderingTemplate ID="ListForm" runat="server"> <Template> <SPAN id='part1'> <SharePoint:InformationBar runat="server"/> <wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbltop" RightButtonSeparator=" " runat="server"> <Template_RightButtons> <SharePoint:NextPageButton runat="server"/> <SharePoint:SaveButton runat="server"/> <SharePoint:GoBackButton runat="server"/> </Template_RightButtons> </wssuc:ToolBar> <SharePoint:FormToolBar runat="server"/> <TABLE class="ms-formtable" style="margin-top: 8px;" border=0 cellpadding=0 cellspacing=0 width=100%> <SharePoint:ChangeContentType runat="server"/> <SharePoint:FolderFormFields runat="server"/> <eJugnoo:FormFieldIterator runat="server"/> <SharePoint:ApprovalStatus runat="server"/> <SharePoint:FormComponent TemplateName="AttachmentRows" runat="server"/> </TABLE> <table cellpadding=0 cellspacing=0 width=100%><tr><td class="ms-formline"><IMG SRC="/_layouts/images/blank.gif" width=1 height=1 alt=""></td></tr></table> <TABLE cellpadding=0 cellspacing=0 width=100% style="padding-top: 7px"><tr><td width=100%> <SharePoint:ItemHiddenVersion runat="server"/> <SharePoint:ParentInformationField runat="server"/> <SharePoint:InitContentType runat="server"/> <wssuc:ToolBar CssClass="ms-formtoolbar" id="toolBarTbl" RightButtonSeparator=" " runat="server"> <Template_Buttons> <SharePoint:CreatedModifiedInfo runat="server"/> </Template_Buttons> <Template_RightButtons> <SharePoint:SaveButton runat="server"/> <SharePoint:GoBackButton runat="server"/> </Template_RightButtons> </wssuc:ToolBar> </td></tr></TABLE> </SPAN> <SharePoint:AttachmentUpload runat="server"/> </Template> </SharePoint:RenderingTemplate>
You can use above in your custom Feature, apply custom logic to decide which field to show/hide. Above can also be part of a generic solution that is available for all lists, by providing a configuration page (_layouts) and custom actions link on list settings.
Hope above gives you a good idea about various options available to meet form customization needs. Sometime soon, I'm going to share sample code on codeplex that simply provides users a UI to configure form visibility for any list instead of depending on developers each time they need a form customization.
Watch this space for updates...
UPDATE (July 29, 2008): I have published a follow-up post to my preferred server-side approach to Form Customizations.