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