dynamische Select-Menüs mit JavaScript 0

Posted by fwoeck
on Tuesday, November 04

Wenn man Ajax umgehen möchte, um die Auswahl eines bestimmten Select-Feldes von der Auswahl eines anderen abhängig zu machen, kann man diese Funktion auch mit JavaScript allein auf der Clientseite regeln.

Ein javascript-Controller

Wir legen einen Controller javascript an. Der Trick an der Sache besteht darin, dass wenn der Client später eine URL /javascript/...js aufruft und eine entsprechende Route gesetzt ist, der neue Controller aufgerufen wird und dynamisch ein js-File erzeugen kann.

Hier befüllt der Controller das @jobs-Array, das später mit dem js-Skript auf die einzelnen Customer-Bereiche aufgeteilt wird:

class JavascriptsController < ApplicationController
  def dynamic_jobs
    @jobs = Job.all_cached
  end
end

Die Route dorthin

müsste dann so lauten:

map.connect ':controller/:action.:format'

Der View-Abschnitt

In diesem Falle sollen innerhalb eines Formulars für das Project-Modell die möglichen Jobs von der Auswahl des Customers abhängen:

<% javascript 'dynamic_jobs' %>
...
<% form_for @project do |f| %>
  ...
<p>
  Kunde<br />
  <%= f.collection_select :customer_id, Customer.all_cached, :id, :name, :prompt => "" %>
</p>

<p id="job_field">
  Job<br />
  <%= f.collection_select :job_id, Job.all_cached, :id, :name, :prompt => "" %>
</p>

Das File dynamic_jobs.js.erb

befindet sich im views/javascripts-Ordner. Es erzeugt das js-File mit den Kunden und Jobs. Die Funktion customerSelect teilt die Daten des Arrays in Kunden ein.

var jobs = new Array();
<% for job in @jobs -%>
  jobs.push(new Array(<%= job.customer_id %>, '<%=h job.name %>', <%= job.id %>));
<% end -%>

function customerSelected() {
  customer_id = $('project_customer_id').getValue();
  options = $('project_job_id').options;
  options.length = 1;
  jobs.each(function(job) {
    if (job[0] == customer_id) {
      options[options.length] = new Option(job[1], job[2]);
    }
  });
  if (options.length == 1) {
    $('job_field').hide();
  } else {
    $('job_field').show();
  }
}

document.observe('dom:loaded', function() {
  customerSelected();
  $('project_customer_id').observe('change', customerSelected);
});

und schließlich

benötigen wir noch einen Helper, der das dynamisch erzeugt js-File in das Rendering einbaut – z.B. in der application_helper.rb:

def javascript(*args)
  args = args.map { |arg| arg == :defaults ? arg : arg.to_s }
  content_for(:head) { javascript_include_tag(*args) }
end