JQuery select multiple after chained select

2.2k views Asked by At

A user should select hosts after selecting some groups. I have build a chained select with the JQuery chained remote Plugin for selecting Hosts via Groups. The following code is being used and working fine:

$('#hosts').remoteChained({
    parents: "#hosts_group",
    url: "ajax/getHosts"
 });
   <select id="hosts_group" name="hosts_group" class="form-control">
         <option value="">Bitte Gruppe selektieren</option>
         <option value="1>Some Groups</option>
   </select>

   <select id="hosts" name="hosts"></select>

But the final result should provide a duallistbox for the Hosts in which a User can select Hosts from any Group. I have tried adding the multiple tag to the hosts select and adding a JQuery DuallistBox via the following snippet:

 $('#hosts').remoteChained({
    parents: "#hosts_group",
    url: "ajax/getHosts"
 }).DualListBox({json: false});

The duallist box is displayed fine, but no hosts are shown when I select a group.

JSON Data looks like the following:

[
    {'name': 'host1', 'id': '1'},
    {'name': 'host2', 'id': '2'}
]

When selecting a different group, the json contains also the different hosts. The chained select plugin requests the data via the following request: ajax/getHosts/?hosts_group=selectedId

Just using the chained select with a normal multiple select works fine. The problem is displaying the json data, which differs for each select, in the duallist box.

I have tried to build a JsFiddle example, but it is not working, because the external library won't be loaded and I don't really understand how I can manually provide the json via different selects.

1

There are 1 answers

0
Jonathan Walters On BEST ANSWER

Okay, I think I got this working the way you intend it to. The problem stems from the fact that DualListBox is trying to initialize itself before remoteChained has finished populating the select box. The ideal solution is on remoteChained completion, initialize DualListBox. Unfortunately, remoteChained doesn't seem to have a callback function, making this slightly more tricky. Here's my (slightly hacky) solution:

$(document).ready(function() {
    // setup remote chained
    $('#hosts').remoteChained({
        parents: "#hosts_group",
        url: "ajax/getHosts"
    });

    // set up dualList when change is triggered
    $('#hosts_group').on("change", function() {

        // if the option wasn't the first one
        if($(this).find("option:selected").val() != "") {
            setUpDualList();
        } else {
            // left as an exercise
            //putHostsSelectBoxBackIfItWasDestroyedByDualList();
        }
    });
});

function setUpDualList() {
    if(!hostsChanged()) {
        // because there's no callback, we have continually check if json is complete
        setTimeout(function() { setUpDualList(); }, 300);
    } else {
        // this actually does it.
        $("#hosts").DualListBox({json:false});
    }
}

function hostsChanged() {
    /*
    * this is VERY simplistic.  It will have to handle if #hosts was
    * 'changed' to have the same content, or if it was changed to 
    * something that has the same number of options, etc.  This ONLY
    * works for the very simple case you presented above.
    */
    return $("#hosts").find("option").length != 0;
}

The HTML can stay the same:

<select id="hosts_group" name="hosts_group" class="form-control">
    <option value="">Bitte Gruppe selektieren</option>
    <option value="1">Some Groups</option>
</select>

<select id="hosts" name="hosts"></select>

However, because DualListBox is destructive, it may be better to create a "hosts" select and a "hosts_destroyable" select. The destroyable select would simply duplicate "hosts" on ajax complete, initialize DualList, and hide "hosts". When the DualList needs to be hidden again (because the user changed which group was selected) then the "hosts_destroyable" would need to be recreated.

So. Above is the short, hacky, yes-this-works-but-it-needs-help solution. Below is a step by step full solution.

  • Initialize remoteChained

  • On change of #hosts_group to a valid group:

    1. $("#hosts").show();

    2. Monitor #hosts and figure out when remoteChained has successfully completed the json request.

    3. When request is complete, duplicate #hosts to a temporary #hosts_temp

    4. $("#hosts_temp").DualListBox({json:false})

    5. $("#hosts").hide();

  • On change of #hosts_group to invalid group (e.g. "Bitte Gruppe selektieren"):

    1. Destroy DualListBox (not sure what all is created, remove from DOM somehow if it exists)

    2. $("#hosts").show();