Ryan Mortier
Ryan Mortier

Reputation: 873

Can't get jQuery chained ajax selects working

I'm trying to implement chained ajax selects from this jQuery plugin: http://www.appelsiini.net/projects/chained

I'm using the remote method.

I have a problem where my select boxes show the "default" (blank) value last in the select as seen here:

This is a problem because I have 5 chains, so when the blank value isn't selected by default, it does 5 sequential lookups. It also isn't working like it shows on the demo page where the default value is selected by default instead of a real value.

A JSON request from my server returns this:

{"":"","1":"Test #1","2":"Test #2"}

So as you can see, it's not the order that my JSON is returning.

This is my HTML:

<label class="control-label" for="branch">Branch</label>
<select id="branch" name="branch">
    <option value=""></option>
    <option value="1">Foo</option>
    <option value="2">Bar</option>
</select>
<label class="control-label" for="facility">Facility</label>
<select id="facility" name="facility">
    <option value=""></option>
</select>

<script src="/js/chained.js"></script>
<script>
    $(document).ready(function() {
        $("#facility").remoteChained("#branch", "/src/record.json.php");
    } );
</script>

So now I'm lost and since I can't read/write JavaScript very well, I'm hoping someone can see the issue and help me out.

Upvotes: 2

Views: 2703

Answers (2)

Okan Kocyigit
Okan Kocyigit

Reputation: 13421

It happens because,

Chrome and probably Opera sort object properties automatically

So your JSON also is sorted in for loop.

var json = {"":"","1":"Test #1","2":"Test #2"};
for(var i in json)
   console.log(i);

/* Result : 1 2 (null) */

DEMO

Solution 1:

If you change your index as string that will not be sorted.

var json = {"":"","t1":"Test #1","t2":"Test #2"};
for(var i in json)
   console.log(i);

/* Result : (null) t1 t2 */

DEMO

Solution 2:

Changing plug-in

Here is the edited plugin code that works with array,

  /*
 * Remote Chained - jQuery AJAX(J) chained selects plugin
 *
 * Copyright (c) 2010-2011 Mika Tuupola
 *
 * Licensed under the MIT license:
 *   http://www.opensource.org/licenses/mit-license.php
 *
 */

(function($) {

    $.fn.remoteChained = function(parent_selector, url, options) { 

        return this.each(function() {

            /* Save this to self because this changes when scope changes. */            
            var self   = this;
            var backup = $(self).clone();

            /* Handles maximum two parents now. */
            $(parent_selector).each(function() {
                $(this).bind("change", function() {

                    /* Build data array from parents values. */
                    var data = {};
                    $(parent_selector).each(function() {
                        var id = $(this).attr("id");
                        var value = $(":selected", this).val();
                        data[id] = value;
                    });

                    $.getJSON(url, data, function(json) {
                        var selectedVal;
                        /* Clear the select. */
                        $("option", self).remove();

                        /* Add new options from json. */
                        for (var key in json.options) {
                            var k = json.options[key];
                            /* This sets the default selected. */
                            if ("selected" == k.name) {
                                selectedVal = k.value;
                                continue;
                            }
                            var option = $("<option />").val(k.value).append(k.name);
                            $(self).append(option);    
                        }

                        /* Loop option again to set selected. IE needed this... */ 
                        $(self).children().each(function() {
                            if ($(this).val() == selectedVal) {
                                $(this).attr("selected", "selected");
                            }
                        });

                        /* If we have only the default value disable select. */
                        if (1 == $("option", self).size() && $(self).val() === "") {
                            $(self).attr("disabled", "disabled");
                        } else {
                            $(self).removeAttr("disabled");
                        }

                        /* Force updating the children. */
                        $(self).trigger("change");

                    });
                });

                /* Force updating the children. */
                $(this).trigger("change");             

            });
        });
    };

    /* Alias for those who like to use more English like syntax. */
    $.fn.remoteChainedTo = $.fn.remoteChained;

})(jQuery);

To work with this updated plugin, you should use this JSON format,

{
    "options" : [
      { "value" : "", "name" : ""},
      { "value" : "1", "name" : "Test #1"},
      { "value" : "2", "name" : "Test #2"},
    ]
}

If you want to set a default selected item (for example "Test #1" is selected), so you can do that like this,

{
    "options" : [
      { "value" : "", "name" : ""},
      { "value" : "1", "name" : "Test #1"},
      { "value" : "2", "name" : "Test #2"},
      { "value" : "1", "name" : "selected"}
    ]
}

How can I use this edited plugin?

Just clear all the code in /js/chained.js than paste the new one.

Upvotes: 1

Dave L.
Dave L.

Reputation: 9781

It looks like the JSON returned from the server is wrong.

It should contain a selected field like this:

{"":"--","3-doors":"3 doors","5-doors":"5 doors","coupe":"Coupe","cabrio":"Cabrio","selected":"coupe"}

That is taken from the examples here:

http://www.appelsiini.net/projects/chained

In your case the server should return:

{"":"","1":"Test #1","2":"Test #2","selected":""}

Upvotes: 0

Related Questions