Question

I have a view with 2 select boxes which are "cascading". A user selects a value from the first box and the second is populated based on the new value. This is done with Select2's query option, and works fine on the first load of the page. However, when I post the page and then render it, both select boxes already have values (say A and 1), but the dependent checkbox is not initialized. I have done a few things with initSelection and it didn't help much, sometimes just getting me into an loop.

What I am trying to do is this:

  1. Link the two boxes
  2. When the first box changes, reset the data in the second box and clear the value
  3. When the page is re-drawn, and a value has already been selected (e.g. response to POST)
    1. Go to server and get the data
    2. Show the correct value for the existing <input type='hidden' value='xxx'>
    3. if that value exists in the list, of course
    4. if not, set value to blank (optionally fire jquery validation
  4. Searching/constant querying is not needed. Just load once on change

I am thinking about changing this entire, so if this is really the wrong way to go about this, I'd be happy to know.

// caches ajax result based on `data` 
// if data has been requested before, retrieves from the cache (nothing special)
// based on other code that did it all inside the `query` function directly
var locationsCache = new AjaxCacheClassThing( { 
        url: '...', 
        data: function() { return { masterId: $('#ParentBox').val(); } }
});

$(function() { 
    $('#ParentBox').change(function () {
            $('#ChildBox').select2('data', null);
    });
    $('#ChildBox').select2({
            query: locationsCache.queryCallbackHandler,
            selectOnBlur: true,
    });
});

The HTML uses the standard MVC helpers, and the HTML is rendered just fine.

 @Html.DropDownListFor(m => m.ParentBox, SelectListOfStuff) // standard <select>
 @Html.HiddenFor(m => m.ChildBox)

Here is how this scenario goes:

  1. ParentBox is required (no empty option)
  2. First Load: there is no value selected
    • Open the DependentBox
    • Ajax query issues correctly
    • Dropdown populates as expected
  3. Second Load
    • Master box selects value just fine
    • ChildBox hidden input has value="xx" just fine
    • It does not show a selected item
    • Clicking dropdown populates the box as expected (from cache)
Était-ce utile?

La solution

After some time spent, and lots of time on here and other places, I figured out how this all works (at least some parts of it!). Way simpler than I thought it was, but still surprised this isn't supported out of the box in some way. Seems like a really common request.

  1. query and ajax and initselection aren't that useful in this scenario
    1. They query each time a the search box changes (not desired)
    2. They complicate everything
  2. You need to init the select2 manually
  3. If you use { data: ... } then you don't need query or ajax
  4. Set the "value" on your hidden input if you have one, so the item gets selected
  5. You have to recreate the box when you get new data
  6. It is really simple. This is the simplest case, using no extra features or attributes

Javascript:

$(function() { 
    $('#ParentBox').change(createChildSelect2);
    createChildSelect2();
});

function createChildSelect2() {
    makeAjaxRequest( function( newData ) {
         $('#ChildBox').select2( { data: newData } );
    });
}

function makeAjaxRequest(callback) {
    // calls a.jsp?parentId={?} and then the callback when done. 
    jQuery.ajax({
        url: 'a.jsp', dataType: 'json', 
        data: function() { 
            return { parentId: $("#parentBox").val() };
        }
    })
    .done(function (data) {
        callback(data);
    });
}

The HTML is all the same. A type=text and type=hidden both work:

<select id="ParentBox">
    <option ... > 
    <option ... >
<select>

<input id="ChildBox" type="hidden" class="input-medium" value="1"/>

Or using Razor:

@Html.DropDownListFor(m => m.MasterBox, SelectListOfStuff) // standard <select>
@Html.HiddenFor(m => m.DependentBox)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top