Wednesday, February 14, 2007

How to disable fields on EditForm.aspx. WSS 3.0 version.

I had a task to disable or make read-only some of a SharePoint list fields. I did not wanted to do much development and found some very good solutions for WSS 2.0: How can I make a field read-only? How can JavaScript’ers create custom EditForm without understanding CAML and .NET !

But in case with WSS3.0 these solutions do not work properly because it is very hard to calculate edit element name or id and in my solution I use title attribute of input or select elements generated by ListFormWebPart web part:

<SELECT 
id=ctl00_m_g_4cfb4dc8_9323_4849_bbfb_95af4cc4f470_ctl00_ctl02_ctl00_ctl01_ctl00_ctl00_ctl02_ctl00_ctl00_ctl04_ctl00_Lookup 
title=Company 
name=ctl00$m$g_4cfb4dc8_9323_4849_bbfb_95af4cc4f470$ctl00$ctl02$ctl00$ctl01$ctl00$ctl00$ctl02$ctl00$ctl00$ctl04$ctl00$Lookup> 
<OPTION value=0 selected>(None)</OPTION> 
<OPTION value=6>Transfield Services</OPTION>
</SELECT>

So I created a JavaScript function and placed it after the ListFormWebPart:

<SCRIPT language=javascript>
/// <summary>
/// Disables EditForm field for the specified column title
/// </summary>
function DisableField(title)
{
    for(var i = 0; i < document.all.length; i++)
    {
        var el = document.all[i];
        // find html element with specified title
        if(el.title == title)
        {
            el.disabled = true; // disable
            break;
        }
    }
}
DisableField("Company");
DisableField("Site/Industry");
</SCRIPT>

And these two fields are disabled for editing.

But this ListFormWebPart web part is a tricky thing and creates dropdown lists in different way depending on amount of their items:

Drop down list 1:

<SELECT 
id=ctl00_m_g_4cfb4dc8_9323_4849_bbfb_95af4cc4f470_ctl00_ctl02_ctl00_ctl01_ctl00_ctl00_ctl02_ctl00_ctl00_ctl04_ctl00_Lookup 
title=Company 
name=ctl00$m$g_4cfb4dc8_9323_4849_bbfb_95af4cc4f470$ctl00$ctl02$ctl00$ctl01$ctl00$ctl00$ctl02$ctl00$ctl00$ctl04$ctl00$Lookup> 
<OPTION value=0 selected>(None)</OPTION> 
<OPTION value=6>Transfield Services</OPTION>
</SELECT>

Drop down list 2:

<INPUT class=ms-lookuptypeintextbox 
onkeypress=HandleChar() 
id=Text1 
onkeydown=HandleKey() title=Site/Industry 
onfocusout=HandleLoseFocus() 
onchange=HandleChange() 
value="Transfield Services Generic Documents" 
name=ctl00$m$g_4cfb4dc8_9323_4849_bbfb_95af4cc4f470$ctl00$ctl02$ctl00$ctl01$ctl00$ctl00$ctl03$ctl00$ctl00$ctl04$ctl00$ctl01 
choices="ACT Housing TFM Contracts232ADI Alliance - FFG Refit &amp; Upgrade Project6...<here goes a very long list of choices>" 
match="" optHid="SPSite_x002F_Industry_Hidden" 
opt="_Select">
<IMG 
style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; VERTICAL-ALIGN: middle; BORDER-RIGHT-WIDTH: 0px" 
onclick="ShowDropdown('ctl00_m_g_4cfb4dc8_9323_4849_bbfb_95af4cc4f470_ctl00_ctl02_ctl00_ctl01_ctl00_ctl00_ctl03_ctl00_ctl00_ctl04_ctl00_ctl01');" 
alt="Display lookup values" 
src="INFORM%20Documents%20-%20TMB-0000-SA-9898_files/dropdown.gif">

Thus dropdown list 2 is made of text box and image button which should be disabled as well.

This image button can be found by control id of a text box mentioned in onclick event handler which uses this id in ShowDropdown function call. So this button can be found by content of onclick attribute. Since collection of elements in document.all places elements in order of their declaration in document then we do not need to search all this image button in all the elements but instead of this can check the next element after the have just found element.

Disable field javascript version 2:

<SCRIPT language=javascript>
/// <summary>
/// Disables EditForm field for the specified column title
/// </summary>
function DisableField(title)
{
    for(var i = 0; i < document.all.length; i++)
    {
        var el = document.all[i];
        // find html element with specified title
        if(el.title == title)
        {
            el.disabled = true; // disable
 
            // if the next element has a reference to the current element
            // then disable if as well
            if(i < document.all.length - 1)
            {
                var el2 = document.all[i + 1];
                if(el2.outerHTML.indexOf(el.id) > 0)
                {
                    el2.disabled = true;
                }
            }
            break;
 
        }
    }
}
DisableField("Company");
DisableField("Site/Industry");
</SCRIPT>

16 comments:

PradeepVizz said...

Hi man ! that was really great ! many thanks ! i have just started off with Sharepoint, so can you please tell me how to edit the ListViewWebPart? using which tool should i do the same ? please tell me !

Unknown said...

That worked for me. However, on my form, i have a control that is of type person/group. there is no title associated with this control.
how do i disable such a control ?

Unknown said...

Any help on this will be greatly appreciated.

Thanks

BigHeat said...

THANK YOU! This has been a nagging problem for us for some time and your post is our much-needed needle in a haystack of unclear, incomplete, or otherwise useless options.

THANK YOU AGAIN!

Unknown said...

hi,
for some reason when the user click OK on the editform.asp page, the field that has been set to read-only deletes the value. is there a way to retain the even if the user saves the form w/o any "real" updates? thanks.

Unknown said...

Thank You for the Post. That was a very good stuff...
But i have 1 more additional condition associated to disabling feilds. Can i chk for User Permissions before disabling any field...????

Unknown said...

Great stuff! Worked for me but can I check for Sharepoint group permissions before disabling it?

Kathleen said...

Hello,
I am a newbie, so forgive if the question is 'stupid'...
I've copied the javascript to the editform.aspx page below the ListformWebPart. When I press the save button however, it gets removed from the aspx code (if I place it elsewhere in a 'asp:Content' it stays (but ofcourse it doesn't do what I want it to do.
Any idea why?

Kathleen said...
This comment has been removed by the author.
Carlos Vigo said...

@Graham

Dear Graham, in the given javascript code can you change the "disabled" for the "readOnly" property?

Instead of: el.disabled = true;
try: el.readOnly = true;

Doing so, it will be possible for the EditForm.aspx to save whatever you type in.

I assume that any element being disabled implies that it won't set any value in the POST or GET request.

Paisley said...
This comment has been removed by the author.
Paisley said...

Kathleen - or other newbies
-In order to put code into a sharepoint page it needs to be in a webpart

You are probably used to doing that from the browser by going into edit mode - but for the forms pages (editform.aspx) you need this trick: in order to get to edit mode append a qs parameter to your url
yoursiteurl?ToolPaneView=2

Once you have added a cewp modify shared webpart - and get the "code view" and paste in your js

Then when you go back to SPD again you will have access to the js to mess with --

Sanja said...

Not working! it realy make it read only, but only if you not planning to make changes on that item, if you change some other column value, you will notice that it will reset values of drop down fields to default value !

Devotion I love to Share said...

This is so sweet. simple.. Thanks a lot...

Devotion I love to Share said...

this is cool... thanks a lot . this is a real helpful code..

Devotion I love to Share said...

This is so sweet. simple.. Thanks a lot...