Wednesday, 2 November 2011

Hiding fields in NewForm.aspx

Sometimes you may want to set a field in a SharePoint list to pre-populate with a default value. However, SP still allows your site visitors to alter the value via the New Item form. For example, when I want to capture data supplied by the visitor, but I know only admin staff will be looking at the data, I'll often assign the default value of "Edit Details" to the Title field, so that admin staff know to click on the "Edit Details" hyperlink to see details of that List row.

One answer is to edit the NewForm.aspx page so that the Title field is not displayed. That way site visitors can't change the pre-set default value for the field.

Here's how ...

1. Open SharePoint Designer and navigate to the site that contains the list or document library you wish to customize.

2. Expand the folder named “Forms” under the desired list or document library. You should see about four .aspx pages (AllItems.aspx, EditForm.aspx, NewForm.aspx, etc)


Edit the NewForm.aspx file, and add the Javascript directly ...
3. Check out and open the NewForm.aspx page and switch to the “code” view to edit the HTML of the page.

4. Paste this JavaScript code immediately below the the following HTML tag (usually line 14):
 <asp:Content ContentPlaceHolderId=”PlaceHolderMain” runat=”server”> 

<script language="javascript" type="text/javascript">
_spBodyOnLoadFunctionNames.push("hideFields");
function findacontrol(FieldName) {
   var arr = document.getElementsByTagName("!");
   // get all comments
   for (var i=0;i < arr.length; i++ )
   {
      // now match the field name
      if (arr[i].innerHTML.indexOf(FieldName) > 0)
      {         return arr[i];      }
   }
}

function hideFields() {
   var control = findacontrol("Title");
   control.parentNode.parentNode.style.display="none";
   control = findacontrol("Document Link");
   control.parentNode.parentNode.style.display="none";
   control = findacontrol("PublishDate");
   control.parentNode.parentNode.style.display="none";

}
</script>


This will add the JavaScript to the HTML inside the content placeholder tag. 
Note: be sure to include the entire script above, including the <script> and </script> tags.


5. Modify the “hidefields()” section of the JavaScript code to refer to each SharePoint list field name to hide.  For example, the code sample above will hide the SharePoint fields named Title, Document Link, and PublishDate.  Notice that you do not need to worry about internal field names or field types like other JavaScript techniques, you simply need to know the name of the field.

6. Save the changes and check the page back in.  Select “Yes” when prompted to “… customize the page from the site definition …”

7. Test the form

Wednesday, 14 September 2011

Extract User Name for Workflow Email

We've been searching hard for a solution or workaround to the problem of including a User's name in a Workflow email in SharePoint 2007 (it's a known omission), and were just about to give up when fellow hive member Steve came up with this nifty workaround, by adding some JavaScript to the NewForm.aspx file.

We can take advantage of the fact that SharePoint always knows who you are ...
The idea is to grab the text displayed at the top right of the browser that says, "Welcome John Smith", then render it into a hidden field called Username in the list. You can then call the hidden field in the Workflow email and Robert, as they say, is your mum's brother.

1. So, in SharePoint Designer, open the NewForm.aspx file associated with the list you're attaching the Workflow to.
2. Go to line 66 and replace this code:

<asp:Content ContentPlaceHolderId="PlaceHolderTitleAreaClass" runat="server">
<script id="onetidPageTitleAreaFrameScript">
   document.getElementById("onetidPageTitleAreaFrame").className="ms-areaseparator";
</script>
</asp:Content>

with this:

<asp:Content ContentPlaceHolderId="PlaceHolderTitleAreaClass" runat="server">
<script id="onetidPageTitleAreaFrameScript">
   var userText = document.getElementById('ctl00_m_g_ca8da27f_3ce7_4d29_9adf_e1a96ec0ff6b_ctl00_ctl04_ctl05_ctl00_ctl00_ctl04_ctl00_ctl00_TextField');
   userText.value = document.getElementById("zz6_Menu").innerText.substring(8);
   userText.parentNode.parentNode.parentNode.style.display = "none";
   //document.getElementById("onetidPageTitleAreaFrame").className="ms-areaseparator";
</script>
</asp:Content>

The reference to zz6_Menu is for identifying where on the page the logged-in user's name is appearing (the "Welcome" drop-down menu). But you should double-check this by going View Source on the NewForm.aspx, as I've found the identifier varies depending on your SharePoint set-up.

The getElementById method is identifying the List field where you want to paste the User's Name. You'll have to View Source in order to find out what the ID Number is for the field in your list.

The final line of the new script hides the Username field (used for storing the name) on the Input form. You don't want your end users filling in their name manually.

I found that the original line of script was preventing the new script from working, so I moved it to the end of the sequence and the whole thing started working. So, just to be safe, I commented out the original line of script.

Once this is done, you can add a call in your Workflow Email to pick up the User's name from the Username field you've already added to your Custom List.

For added thoroughness, you should add an amended version of this code to the EditForm.aspx page, so that if the user comes back to the list later to edit their data, they are unable to edit the text of their name. Just open the EditForm.aspx page and alter the code at line 67 to:

<asp:Content ContentPlaceHolderId="PlaceHolderTitleAreaClass" runat="server">
<script id="onetidPageTitleAreaFrameScript">
var userText = document.getElementById('ctl00_m_g_8f8fe63d_e6dc_4f9e_b021_8c653a7bf520_ctl00_ctl04_ctl01_ctl00_ctl00_ctl04_ctl00_ctl00_TextField');
userText.parentNode.parentNode.parentNode.style.display = "none";
//document.getElementById("onetidPageTitleAreaFrame").className="ms-areaseparator";
</script>
</asp:Content>

Note the different value for GetElementById, as this is a different field in a different form.

Hope this helps someone.