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>
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