As you might have noticed already, SharePoint (both 2007 and 2010) will render your lookup drop down column differently depends on the number of item in the drop down list. If you have less than 20 items, SharePoint will just render the drop down using the normal drop down list control.
However SharePoint will change the rendering style when there is more than 20 items. Instead of the simple drop down list control, it will be changed to a textbox + ajax + filtering list, like the following:
So when you start typing in the textbox, it filters the options, allows the user to select an item from a large list. There are pros, and of course there are cons:
- If you decide to select from the list, you need to do a double click in order to pick an option
- The free-text box gives an impression that you can free-text, which ends up saving empty string
- Inconsistent user experience if you have other drop down list in the form that has less than 20 items.
- There are some rendering issue for the Ajax Drop Down list in SharePoint 2010
To get around this, I have implemented a JQuery solution. Basically the script does the following if the drop down has more than 20 items:
- Hide the text box
- Hide the drop down arrow
- Provision the options in a simple drop down list, register an OnChange event to set the lookup hidden field that SharePoint is using.
- Add the drop down to the page.
Insert the following script to the New/Edit form (by using a content editor web part or custom ribbon javascript). I am assuming that you have a reference to the JQuery library in your master page.
Code Snippet
- <script>
- $(document).ready(function () {
- // Name of the column (Display Name)
- var columnName = "Lookup";
- // Override the Drop Down List
- OverrideDropDownList(columnName);
- // Main Function
- function OverrideDropDownList(columnName) {
- // Construct a drop down list object
- var lookupDDL = new DropDownList(columnName);
- // Do this only in complex mode...
- if (lookupDDL.Type == "C") {
- // Hide the text box and drop down arrow
- lookupDDL.Obj.css('display', 'none');
- lookupDDL.Obj.next("img").css('display', 'none');
- // Construct the simple drop down field with change trigger
- var tempDDLName = "tempDDLName_" + columnName;
- if (lookupDDL.Obj.parent().find("select[ID='" + tempDDLName + "']").length == 0) {
- lookupDDL.Obj.parent().append("<select name='" + tempDDLName + "' id='" + tempDDLName + "' title='" + tempDDLName + "'></select>");
- lookupDDL.Obj.parent().find("select[ID='" + tempDDLName + "']").bind("change", function () {
- updateOriginalField(columnName, tempDDLName);
- });
- }
- // Get all the options
- var splittedChoices = lookupDDL.Obj.attr('choices').split("|");
- // get selected value
- var hiddenVal = $('input[name=' + lookupDDL.Obj.attr("optHid") + ']').val()
- if (hiddenVal == "0") {
- hiddenVal = lookupDDL.Obj.attr("value")
- }
- // Replacing the drop down object with the simple drop down list
- lookupDDL = new DropDownList(tempDDLName);
- // Populate the drop down list
- for (var i = 0; i < splittedChoices.length; i++) {
- var optionVal = splittedChoices[i];
- i++;
- var optionId = splittedChoices[i];
- var selected = (optionId == hiddenVal) ? " selected='selected'" : "";
- lookupDDL.Obj.append("<option" + selected + " value='" + optionId + "'>" + optionVal + "</option>");
- }
- }
- }
- // method to update the original and hidden field.
- function updateOriginalField(child, temp) {
- var childSelect = new DropDownList(child);
- var tempSelect = new DropDownList(temp);
- // Set the text box
- childSelect.Obj.attr("value", tempSelect.Obj.find("option:selected").val());
- // Get Hidden ID
- var hiddenId = childSelect.Obj.attr("optHid");
- // Update the hidden variable
- $('input[name=' + hiddenId + ']').val(tempSelect.Obj.find("option:selected").val());
- }
- // just to construct a drop down box object. Idea token from SPServces
- function DropDownList(colName) {
- // Simple - when they are less than 20 items
- if ((this.Obj = $("select[Title='" + colName + "']")).html() != null) {
- this.Type = "S";
- // Compound - when they are more than 20 items
- } else if ((this.Obj = $("input[Title='" + colName + "']")).html() != null) {
- this.Type = "C";
- // Multi-select: This will find the multi-select column control on English and most other languages sites where the Title looks like 'Column Name possible values'
- } else if ((this.Obj = $("select[ID$='SelectCandidate'][Title^='" + colName + " ']")).html() != null) {
- this.Type = "M";
- // Multi-select: This will find the multi-select column control on a Russian site (and perhaps others) where the Title looks like 'Выбранных значений: Column Name'
- } else if ((this.Obj = $("select[ID$='SelectCandidate'][Title$=': " + colName + "']")).html() != null) {
- this.Type = "M";
- } else
- this.Type = null;
- } // End of function dropdownCtl
- });
- </script>
The script will then turn the complex drop down list (if it has more than 20 items) to the simple drop down list:
Originally I extended the
SPServices JQuery Library to fix the drop down issue. So you may find that my scripts contains little portion of the library. I have integrated the above solution with the Cascading Drop Down list function provided by the SPServices library. Let me know if you want to obtain the extended script.
Update:
Since there are request for the Extended SPServices, I have make it available for download. You can download it from
here. (Please rename the extension from .txt to .js)
Few notes before you use this:
1. This extended version is based of SPServices version 0.5.7
2. I have extended SPCascadeDropDowns and called the new function SPCascadeDropDownsEx
3. The original SPServices expects you to have the parent-child list in the following format:
Parent1 - Child1a
Parent1 - Child1b
Parent1 - Child1c
Parent2 - Child2a
Parent3 - Child3a
Parent3 - Child3b
However I have changed this so that it works with a child list and a parent list. For example, I have a child list with list item Child1a, Child1b, Child1c, Child2a, Child3a, Child3b. And then I create a parent list with a multi-valued lookup child colume like this:
Parent1 - Child1a, Child1b, Child1c
Parent2 - Child2a
Parent3 - Child3a, Child3b
(Sorry for the rough explanation, I will include screenshots when I have the system around)
And this is how I invoked the function:
// Enable Cascading Drop down for Department
$().SPServices.SPCascadeDropdownsEx({
relationshipList: "Department",
relationshipListParentColumn: "Title",
relationshipListChildColumn: "AreaOfImpact",
parentColumn: "Department",
childColumn: "Area Of Impact",
relationshipListType: "LookupMultiValue",
promptText: "--- Please select ---",
debug: false
});
So in the above script:
- relationshipList is the parent list
- relationshipListParentColumn is the name of the parent column in the parent list
- relationshipListChildColumn is the name of the childLookup column in the parent list
- parentColumn is the display name of the parent drop down list
- childColumn is the display name of the child drop down list
- relationshipListType is the type of the relationshipListChildColumn in the parent list