Possible bug in SPComplexToSimpleDropdown

Jun 23, 2014 at 9:32 PM
Edited Jun 23, 2014 at 10:11 PM
I'm trying to debug an issue I'm having with cascading dropdowns on a custom list form created as a data view/form web part using 0.7.2. The cascade works properly in that it is filtering correctly, but it is not saving the child value back to the list on creation or edit, it works without issue on the ootb list forms. The flow goes like this:
listName: "New Hire",       
relationshipList: "Floors",
        relationshipListParentColumn: "Building",
        relationshipListChildColumn: "Title",
    parentColumn: "Building",
        childColumn: "Floor",
        selectSingleOption: true,
        simpleChild: true,
        debug: false
simpleChild calls genContainerId("SPComplexToSimpleDropdown", opt.columnName); to generate the select, this results in an id like SPComplexToSimpleDropdown_undefined.

This returns undefined because genContainerId assumes you are on a list form:
function genContainerId(funcname, columnName) {
        return funcname + "_" + $().SPServices.SPGetStaticFromDisplay({
            listName: __$().SPServices.SPListNameFromUrl()__,
            columnDisplayName: columnName
I'm assuming this is failing because the list name isn't being passed into SPGetStaticFromDisplay. The rendered Select has the proper Title of Floor, but the ID is wrong which blows up the form as I have 2 cascades on this form. It doesn't know what data to associate with what as they are both SPComplexToSimpleDropdown_undefined.
Jun 24, 2014 at 1:32 AM
Is the list nam in the URL? In the regular place?
I have a feeling you are right. Maybe the problem is SPListNameFromUrl()...

Paul T.

-- Sent from Mobile

Jun 24, 2014 at 1:53 AM
I should have specified that this is a page in the pages library, so no, it is not in the URL.

Sent from my iPhone

Jun 24, 2014 at 2:00 AM
Yeah, I'm pretty sure that is going to be the problem.
You could change your version to have genContainerId accept the list on input as an optional param; if defined, use it; if not, then call SPGetListNameFromUrl.
Then change cascadeDropdown to pass the list name on to it.

Paul T.

-- Sent from Mobile

Jun 24, 2014 at 2:30 AM
Since our version is minified and bundled in a separate js file as part of our branding, I decided to scrap the cascade call in this case and rearchitect the relationship into a single list. Forking it in this case wouldn't work so I'll have to do something custom.

I did look, and this is present in the latest version too. It might explain some of the other issues people have reported about values not persisting on edit forms and such.

Sent from my iPhone

Jun 24, 2014 at 2:34 PM
In newer versions, you can pass in the value of listName for just this situation. If you can't upgrade (jeez, it's time!) Then you'll need to work around it.

Jun 24, 2014 at 3:07 PM
I am passing in listName, but it doesn't do anything for simpleChild. The cascade does work in this instance, but values do not persist because the script bombs out. If you want more info let me know.
Jun 24, 2014 at 6:47 PM
I see what you are saying. genContainerId isn't respecting the listName that you've passed in. BUG!

I think this will fix it:
    // Generate a unique id for a containing div using the function name and the column display name
    function genContainerId(funcname, columnName, listName) {
        var l = listName !== undefined ? listName : $().SPServices.SPListNameFromUrl();
        return funcname + "_" + $().SPServices.SPGetStaticFromDisplay({
            listName: l,
            columnDisplayName: columnName
    } // End of function genContainerId
and changing the call to SPComplexToSimpleDropdown like this:
        // If requested and the childColumn is a complex dropdown, convert to a simple dropdown
        if (opt.simpleChild === true && childSelect.Type === dropdownType.complex) {
                listName: opt.listName,
                columnName: opt.childColumn
and then picking up the listName in SPComplexToSimpleDropdown:
    // function to convert complex dropdowns to simple dropdowns
    $.fn.SPServices.SPComplexToSimpleDropdown = function(options) {

        var opt = $.extend({}, {
            listName: $().SPServices.SPListNameFromUrl(), // The list the form is working with. This is useful if the form is not in the list context.
            columnName: "", // The display name of the column in the form
            completefunc: null, // Function to call on completion of rendering the change.
            debug: false // If true, show error messages;if false, run silent
        }, options);


        // Build up the simple dropdown, giving it an easy to select id
        var simpleSelectId = genContainerId("SPComplexToSimpleDropdown", opt.columnName, opt.listName);
While I'm at it, I'm adding listName as an option to SPComplexToSimpleDropdown, SPDisplayRelatedInfo, SPFilterDropdown, SPAutocomplete, and SPSetMultiSelectSizes.
Jun 24, 2014 at 6:48 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Jun 24, 2014 at 7:00 PM
p.s. I can't figure out how to contact you, so ping me if you'd like to try the fix.

Jun 24, 2014 at 7:55 PM
Be careful with the following in your solution:

var l = listName !== undefined ? listName : $().SPServices.SPListNameFromUrl();

I think some browser (IE v???) will throw an error if listName is undefined (because your trying to use it)... It may be safer to:

var l = (typeof listName !== "undefined") ? listName : $().SPServices.SPListNameFromUrl();

As Eric mentioned, this may fix some of the issues that (lately) keep popping up here about the field name being _undefined and values not being saved. :)

Paul T

Jun 24, 2014 at 8:05 PM
I've never seen a problem with listName !== undefined before. Have you? I use IE8 a lot with clients, and I think I've stopped worrying about IE6.

Jun 24, 2014 at 8:08 PM
I swear I have... I know I stopped using it after hitting errors somewhere...
in this case, I think (now that I look at it again) that its safe... you are actually initializing listName (because its part of the named input params), but its value is undefined... so it may be ok.

Paul T

Jun 25, 2014 at 2:46 PM
I remember a condition that caused me change my approach of checking for undefined variable. It does go back to the reason on my prior post.

​I was working ​
on some widgets, I was trying check if a sharepoint variable was already set. That variable was set globally by one of the sharepoint js files, and I found that if I checked it before it was defined, it would throw the exception.

Did a quick check in firebug
​ and confirmed this​

If (myinvalidvar === undefined) { console.log("yes"); }

Throws error.
​Again, in this specific case, its not an issue: you are defining (initializing) the listName variable, so it will not give you the ReferenceError.


Jun 25, 2014 at 3:30 PM
I see what you mean. Pasting "myinvalidvar === undefined" into Firebug's console does indeed throw and error. If you use "use strict", you shouldn't be able to use a variable that hasn't been defined.