Frage

I'd gone through the documentation for Ajax.Updater() where the first argument to the constructor is

container (String | Element) – The DOM element whose contents to update as a result of the Ajax request. Can be a DOM node or a string that identifies a node's ID.

But I want to update two select box using the Ajax.Updater(). What should I pass in the first argument? Could it be possible?

For reference, the html look likes:

<select id="options_one">
    <option value="1">One</option>
    <option value="2">Two</option>
    <option value="3">Three</option>
</select>
<!-- some other html code -->
<select id="options_two">
    <option value="1">One</option>
    <option value="2">Two</option>
    <option value="3">Three</option>
</select>

Both <select> contains the same value and should be updated after Ajax success.

War es hilfreich?

Lösung

Got it working. Here's the code:

new Ajax.Request('/request/url', {
    method: 'post',
    parameters: {cid: '12', mid: '45'},
    onSuccess: function(transport) {
        var response = transport.responseText;
        $('options_one').update(response);
        $('options_two').update(response);
    },
    onFailure: function(transport) {
        alert('failed ' + transport.responseText);
    }
});

Update

insertion (String): By default, Element.update is used, meaning the contents of the response will replace the entire contents of the container. You may instead insert the response text without disrupting existing contents. The insertion option takes one of four strings — top, bottom, before, or after — and inserts the contents of the response in the manner described by Element#insert.

So in my case, using Ajax.Updater is not a good choice.

Andere Tipps

First off, you probably don't want to update your select elements like this at all. Perhaps you plan to use them interactively later, right? You may want to choose an option and have that do something in the browser? If you just stuff some options into the body of the select, you won't get that effect, and in some browsers, you won't have any working options, either.

The proper way to change the options of a select on the fly is to manipulate the select element's options collection, like this:

var new_options = {4: "Four", 5: "Five", 6: "Six"}; // or from your Ajax callback
var options_two = $('options_two'); // reference the select element
options_two.options.length = 0; // remove existing options
for(var i in new_options){
  // use the constructor new Option() to create a new option for each new value/label pair
  options_two.options[options_two.options.length] = new Option(new_options[i], i);
};

Done in this manner, any observers you have attached to the select will still work later, and the browser will not lose the thread about what you're doing form-wise.

Second, the Ajax.Updater is a convenience wrapper around Ajax.Request() and Element.update(). You could think of it like this:

new Ajax.Request('your/endpoint', {
  onComplete: function(transport){
    $('your_element').update(transport.responseText);
  }
});

So to answer your question, the way you would use Ajax.Updater in your code would be to wrap both select tags in a common parent, and have your server response return both select tags fully composed. The downside to this, as noted above, is that any callbacks that are already in the page will no longer have a reference to the original select tags -- they're gone, and the replacements would have to have new listeners attached. Leave this page open long enough, and you have a memory leak that will grow each time the pickers are replaced.

To take the two concepts and combine them, here's how I did this in a recent project:

document.on('click', 'input.team', function(evt, elm){
  if($('project_project_template_id')){
    var picker = $('project_project_template_id').enable();
    var team = $$('input.team:checked').first();
    new Ajax.Request('/teams/' + $F(team) + '/project_templates.json', {
      onSuccess: function(xhr){
        var opts = xhr.responseJSON;
        // var none = picker.options[0];
        picker.options.length = 0;
        // picker.options[0] = none;
        opts.each(function(o){
          picker.options[picker.options.length] = new Option(o['name'], o['id']);
        });
      }
    });
  }
});

This is in a Rails application, so there are some conventions working here that are not in my earlier examples, but you should be able to get something going from this. If you had multiple pickers to update, you would just need to nest them in your JSON response, so you had something like this coming from the server:

{"options_one": {4: "Four", 5: "Five"}, "options_two": {6: "Six", 7: "Seven"}}

Then you could update both pickers with one Ajax request.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top