Sanjaya on SharePoint/Microsoft technologies

a blog on technologies like .net, MOSS 2007, wss 3.0 etc

  • Flickr Photos

Filtered lookup field in sharepoint list

Posted by sNjY on February 21, 2008

Recently, I had a requirement where i wanted to filter my lookup field items in a sharepoint list based on some conditions. I found this article, which talks about the same.

http://blog.u2u.info/DottextWeb/patrick/articles/466.aspx

Good article, but for some reason i was not getting the id field for my combo.

Then i figured out the following way of doing the same. its all with the beauty of xml and java script.

It has worked for me, so here it goes, may be this helps for some of us.

1. First create an aspx page with your logic, validations to fetch the items you want to set to the lookup field. Copy the page to 12\TEMPLATE\LAYOUTS to make it an application page. The code should be something like this, where you fetch your values, prepare an xml data and write it to the HTTPResponse.

protected void Page_Load(object sender, EventArgs e){SPWeb web = SPControl.GetContextWeb(this.Context); this.Response.ClearHeaders();this.Response.ClearContent();

this.Response.Cache.SetCacheability(HttpCacheability.NoCache);this.Response.AddHeader(“Content-type”, “text/xml”);

string cmdPattern = @”<Command><Value><![CDATA[{0}]]></Value><Text><![CDATA[{1}]]></Text>

</Command>”;this.Response.Write(@”<?xml version=””1.0″” encoding=””UTF-8″” ?>”);

this.Response.Write(“<Commands>”);//SPView myProjects = web.Lists[“e-PSFs”].Views[“Newly Approved ePSFS”];

SPListItemCollection items = web.Lists[“e-PSFs”].Items; foreach (SPListItem item in items){//Filter the values based on your conditions and write it to the reponse one by one

if ( Convert.ToString(item[“Status”])==“Approved”){this.Response.Write(string.Format(cmdPattern, Convert.ToString(item[“ID”]), Convert.ToString(item[“Title”])));}}

this.Response.Write(“</Commands>”);this.Response.End();web.Dispose();}

At this point, we have our aspx page ready to fetch our items and write it to the HTTPReponse.

2. Add the following javascript section to your page like newform.aspx, editform.aspx etc

<script language=”javascript” type=”text/javascript”>

_spBodyOnLoadFunctionNames.push(“FillLookupFieldItems”);
}
function FillLookupFieldItems()
{
 var ePSFCombo=getTagFromIdentifierAndTitle(‘select’,’Lookup’,’ePSF’);
 if(ePSFCombo==null)
 {
  ePSFCombo=getTagFromIdentifierAndTitle(‘input’,”,’ePSF’);
 }
 
  var request;
  var url = window.location.toString().substring(0,window.location.toString().indexOf(window.location.pathname)) +
      “/_layouts/ISSA/NewlyApprovedePSFs.aspx”; //NewlyApprovedePSFs.aspx is the aspx page we create in step 1.
   if ( window.XMLHttpRequest )
   {
      request = new XMLHttpRequest();
      request.open(“GET”, url, false);
      req.send(null);
   }
   else if ( window.ActiveXObject )
   {
      request = new ActiveXObject(“Microsoft.XMLHTTP”);
      if ( request )
      {
         request.open(“GET”, url, false);
         request.send();
      }
   }
  
   if ( request )
   {  
  
      var commands = request.responseXML.getElementsByTagName(“Command”);
      // for each command found in the returned XML, extract the Text,
      // and value of the item
      ePSFCombo.options.length=0;
   var none=document.createElement(“OPTION”);
   ePSFCombo.options.add(none);
    none.innerText = ‘(None)’;
   none.value = 0;
  
      for ( var i = 0; i < commands.length; i++ )
      {
         var value = commands[i].getElementsByTagName(
            “Value”)[0].firstChild.nodeValue;
         var text = commands[i].getElementsByTagName(
            “Text”)[0].firstChild.nodeValue;
    
   var opt = document.createElement(“OPTION”);
   ePSFCombo.options.add(opt);
   opt.innerText = text;
   opt.value = value;
   
      }
          setSelectedOption(ePSFCombo,0);
         
   }

}

function setSelectedOption(select, value) {
  var opts = select.options;

  var l = opts.length;

  if (select == null) return;

  for (var i=0; i < l; i++) {

    if (opts[i].value == value) {

      select.selectedIndex = i;

      return true;

    }

  }

  return false;

}

function getTagFromIdentifierAndTitle(tagName, identifier, title) {

  var len = identifier.length;

  var tags = document.getElementsByTagName(tagName);

  for (var i=0; i < tags.length; i++) {

    var tempString = tags[i].id;

    if (tags[i].title == title && (identifier == “” || tempString.indexOf(identifier) == tempString.length – len)) {

      return tags[i];

    }

  }

  return null;

}

</script>

You are ready to go.

Please share if you have some other way of doing this.

15 Responses to “Filtered lookup field in sharepoint list”

  1. hah said

    it works 😉

  2. Well, more ‘Sharepointish’ approach to filtered lookup functionality you can have with IT-Dev View Filtered Lookup for WSSv3 and MOSS. It is based on built in Lookup Fieldtype and extends it with cross-site and filter functionality:
    http://www.it-dev.pl/en/Components/SharePoint_Filtered_Lookup.aspx

  3. sNjY said

    your solutionn does not come free ;( its good anyways 😉

  4. Jen said

    I appreciate the article but I don’t understand step 1. You say “First create an aspx page with your logic” but I don’t understand where the code-behind page goes? When you compile there is a dll? What happens to the dll? Thanks for your help!

  5. sNjY said

    thanks Jen.

    Code behind page (*.cs or *.vb) can be placed along with aspx page in layouts folder itself without compiling it as a dll.It works.

    also, if you have a dll, you can gac the dll and refer it in your aspx file within Inherits attribute of page directive.

    Thanks,
    Sanjaya

  6. Jen said

    Hello! Thank you for your response! I got the aspx page working!

    Here is the next issue that I am running into…I have added the code into my newform.aspx page. I went and changed the items that I thought needed to change based on my fields. However, I get a javascript error on the page that says “Options” is null or not an object. I think the problem is here but I am not sure:

    ePSFCombo.options.length=0;
    var none=document.createElement(“OPTION”);
    ePSFCombo.options.add(none);

    I am not sure how to troubleshoot this…any suggestions would be great!
    THanks,
    Jen

    Listed below is the entire codeset that I added to the page:

    _spBodyOnLoadFunctionNames.push(“FillLookupFieldItems”);

    function FillLookupFieldItems()
    {
    var ePSFCombo=getTagFromIdentifierAndTitle(‘select’,’Lookup’,’JenTest’);
    if(ePSFCombo==null)
    {
    ePSFCombo=getTagFromIdentifierAndTitle(‘input’,””,’JenTest’);
    }
    var request;
    //var url=”http://team.crescent.com/sites/commissions/_layouts/leasecomm.aspx”;
    var url = window.location.toString().substring(0,window.location.toString().indexOf(window.location.pathname)) + “/sites/commissions/_layouts/LeaseComm.aspx”;
    if(window.XMLHttpRequest)
    {
    request = new XMLHttpRequest();
    request.open(“GET”, url, false);
    request.send(null);
    }
    else if(window.ActiveXObject)
    {
    request = new ActiveXObject(“Microsoft.XMLHTTP”);
    if (request)
    {
    request.open(“GET”, url, false);
    request.send();
    }
    }

    if(request)
    {

    var commands = request.responseXML.getElementsByTagName(“Command”);

    // for each command found in the returned XML, extract the Text,
    // and value of the item
    ePSFCombo.options.length=0;
    var none=document.createElement(“OPTION”);
    ePSFCombo.options.add(none);
    none.innerText = ‘(None)’;
    none.value = 0;

    for(var i = 0; i < commands.length; i++)
    {
    var value = commands[i].getElementsByTagName(“Value”)[0].firstChild.nodeValue;
    var text = commands[i].getElementsByTagName(“Text”)[0].firstChild.nodeValue;
    var opt = document.createElement(“OPTION”);
    ePSFCombo.options.add(opt);
    opt.innerText = text;
    opt.value = value;
    }
    setSelectedOption(ePSFCombo,0);
    }
    }

    function setSelectedOption(select, value) {

    var opts = select.options;

    var l = opts.length;

    if (select == null) return;

    for (var i=0; i < l; i++) {

    if (opts[i].value == value) {

    select.selectedIndex = i;

    return true;
    }
    }
    return false;
    }

    function getTagFromIdentifierAndTitle(tagName, identifier, title) {

    var len = identifier.length;

    var tags = document.getElementsByTagName(tagName);

    for (var i=0; i < tags.length; i++) {

    var tempString = tags[i].id;

    if (tags[i].title == title && (identifier == “” || tempString.indexOf(identifier) == tempString.length – len)){
    return tags[i];
    }
    }
    return null;
    }

  7. sNjY said

    Jen
    from your code, i assume that you have a lookup field titled JenTest on your page.
    i don see any problem syntactically. Please check if the commands.length is greater than zero.
    The easiest way to debug javascript is with alert.
    pls try placing

    alert(‘test’);

    before and after the line you think can have problem and see if there is alert or not.

  8. Jen said

    Hello Sanjaya,
    I checked the commands.length and it is greater than 0. I am getting 11 results back which is what I should be getting.

    It fails on this line:
    ePSFCombo.options.length=0;

    The error I see from Internet Explorer is “options is null or not an object”.

    Thank you for your help!
    Jen

  9. Jen said

    I have discovered something else. The filtered dropdown works when I have 20 or fewer items in my list… getTagFromIdentifierAndTitle(“select”,”Lookup”,fieldName)

    If I have greater than 20 items and it reads the lookup fields as an input rather select…it starts failing.

    Any ideas why it fails when it sees the field as input?

  10. sNjY said

    Jen,

    yes the field is rendered as input if the number of items is greater than 20, but it should not fail though.

    Let me check it.

  11. Iv said

    Hello,
    Thank you for your post. I have the same problem like Jen had. The filtered dropdown fails only when I have more then 20 items in my list. I am wondering if you found out the solution for this problem.
    Thanks in advance,

    Iv

  12. Majox said

    Try this http://blogs.msdn.com/sharepointdesigner/archive/2007/06/13/using-javascript-to-manipulate-a-list-form-field.aspx

    Here is an example code that works with more then 20 items

  13. PJ said

    Hello Sanjay/Jen/Iv/Majox,

    I am struck with same issue as my lookup as more than 20 items. Please suggest what you have found for this problem?

    Thanks a lot in advance.

  14. ILoveSharePoint said

    Dude.. what a POS sharepoint is.. a royal hack,

    But thanks…

  15. Bob said

    This really had me stumped, not having designer until I realized you can filter lookups without it:
    http://www.sharepointforums.org/forums/moss-development/997-filter-lookup-column.html

Leave a comment