SPCascadingDropdowns Demystified (or Mystified, Depending on Your View)
In my jQuery Library for SharePoint Web Services, one of the most popular functions is $().SPServices.SPCascadeDropdowns. The SPCascadeDropdowns function lets you set up cascading dropdowns on SharePoint forms. What this means is that you can enforce hierarchical relationships between column values. This is sometimes called connected dropdowns or linked dropdowns (or probably other things I haven’t run across yet).
The function uses the GetListItems operation of the Lists Web Service to refresh the allowable values based on relationships which are maintained in reference lists. By implementing this function, you can remove all of the coding requirements to manage the hierarchical relationships (once it is in place) and let your users manage the content.
The requirement that the values be stored in a list seems to baffle many people, as do the basic steps to use the function. I’m not dissing anyone here. I know that there are people using this stuff who don’t have a development background. I see that is a Really Good Thing, and is one of the reasons I’ve implemented the functions in the library the way I have. But what it can mean is that the underlying concepts may be downright foreign.
Here are some explanations of the most common things I see people struggling with. I’m going to add these ideas into the documentation, of course, but I thought a blog post might be a good idea, too, as some of these ideas apply in general.
- The src attribute in <script src="../../jQuery%20Libraries/jquery-1.3.2.js"></script> should point to where *you* put the .js files. You can store them anywhere that makes sense for your needs. To reiterate my suggestion in the documentation: I recommend putting them into a Document Library in the root of your Site Collection called something like jQuery Libraries. However, they can be stored anywhere as long as all users who need to access them have read permissions.
- relationshipListParentColumn and relationshipListChildColumn should be the internal name (also known as the StaticName) for the columns in the relationshipList. parentColumn and childColumn should be the DisplayNames for the columns on the form.
- When you first create a column in a list, the name which you give the column becomes the StaticName.
- The StaticName is encoded, meaning that certain characters are replaced with a set of characters which represent their ASCII value. So if you name a column Product Description, the StaticName will be Product_x0020_Description. Terms & Conditions becomes Terms_x0020__x0026__x0020_Condit. _x0020_ = space (" "), _x0026_ = ampersand ("&"), etc.
- As you can see from the Terms & Conditions example above, the StaticName is limited to 32 characters, including the encoded values.
- If you aren’t sure what the StaticName for a column is, go into List Settings, click on the column name in the Columns section, and look at the URL. At the end of the URL, you’ll see a Query String parameter called Field: &Field=Lead%5Fx0020%5FSource. The string after the = sign is the StaticName, in this case Lead_x0020_Source. The %5F values are the underscores ("_"_ encoded for the URL. I know this can be confusing if you aren’t familiar with these concepts.
- If you subsequently change the column name (like renaming Title to Failure), the StaticName stays static (does not change), but the DisplayName does change.
- One of the dangers of this is that a column is renamed several times and ends up being used for something entirely different than its original intent. Because of this, it’s often better to delete a column and add a new one than renaming it.
- Don’t create the lists to drive the cascading dropdowns *only* to drive the cascading dropdowns. These lists are the best practice way to manage the choices that are available to a user in list columns. This is a key concept way beyond the cascading dropdowns idea:
- Things like States or Regions or Products or Parts ought to be created as Site Columns in the root of your Site Collection which are lookups into lists and then used everywhere in the Site Collection you need them.
- Because the choices are stored in a list, you can manage them as content as opposed to as settings, applying content management rules or workflows, as needed.
- Since the values are stored in one place, a change in the list ripples out to every list or library where the Site Column is used. This is an incredibly powerful capability in SharePoint that is totally underused and ensures information uniformity and a good information architecture.
- By taking advantage of this capability, you can begin to enforce a common taxonomy of concepts which apply across the organization. Rather than calling Product 12345 the Blue Widget and the Left Screwed Thing and the One that J&J Buys, we can all call it Product 12345 and understand what we are all talking about.
Hi Marc,
that ist is all well and nice explained, but there is a little problem when using language packs. We are using difrent display names for each language, and for “parentColumn” and “childColumn” we would need to use the staticName. Is there any chance to modify the code, to use the StaticName for those 2 columns?
Thanks
Robert
@Robert:
That could be a potential enhancement, but that’s the way it works now. You can use $().SPServices.SPGetStaticFromDisplay or $().SPServices.SPGetDisplayFromStatic to get the converses.
M.
Hi Marc,
thanks for the tip, but unfortunately this does not work with different languages. It gives you back only the default display name
I used something like that:
var list_name = $().SPServices.SPListNameFromUrl();
var Udisplay_name = $().SPServices.SPGetDisplayFromStatic ({
listName : list_name,
columnStaticName: “STATIC_COLUMN_NAME”
});
console.log (Udisplay_name);
var Sdisplay_name = $().SPServices.SPGetDisplayFromStatic ({
listName : list_name,
columnStaticName: “STATIC_COLUMN_NAME”
});
console.log (Sdisplay_name);
$().SPServices.SPCascadeDropdowns({
relationshipList: “LIST_NAME”,
relationshipListParentColumn: “STATIC_COLUMN_NAME”,
relationshipListChildColumn: “STATIC_COLUMN_NAME”,
parentColumn: Sdisplay_name,
childColumn: Udisplay_name,
debug:true
});
am I using it wrong?
The script it does work perfectly for the german language (Default) and in console I can see the right DisplayName, but when I Change to French, it breaks and in console I see the same german Display Name.
Thanks,
Robert