How can I make the javascript in my Rails 3 form unobtrusive?
I'm a rails newbie attempting to make an app for managing translations of sets of labels using Rails 3. I haven't gotten too far past scaffolding so as far as I know I'm using Rails 3's default javascript libraries (ie prototype, not jQuery).
I have a form for the names of the label sets, and the desired behaviour is for the names of all current label sets to be populated in a drop-down list ("label_sets"
), and when you select one, it populates the :name
text field ($('label_set_name')
) and disables it. If the drop-down displays the :include_blank
value, a new label set name can be entered. When the form is submitted, the :name
text field gets re-enabled so its value will actually get saved.
This form does perform the desired behaviour, but I think there must be a way to refactor the javascript in :onsubmit
and :onchange
into another file(s) and make it unobtrusive. I've scoured the web for material on making unobtrusive javascript in Rails 3, but have honestly been confused by a lot of it and don't know how to apply it to my case. Could anyone please offer any suggestions? The abbreviated source for my label set form is below:
# app/views/label_sets/_form.html.erb
<%= form_for(@label_set,
:html => { :onsubmit => "$('label_set_name').enable();" }) do |f| %>
# ...
<div class="field">
<%= label "label_sets", t('.label_set') %><br />
<%= select_tag("label_sets",
options_for_select(LabelSet::NAMES),
{ :include_blank => t('.new'),
:onchange => "if (this.value.empty()) {
$('label_set_name').clear();
$('label_set_name').enable();
} else {
$('label_set_name').value = this.value;
$('label_set_name').disable();
}" }) %><br />
</div>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
# ...
<% end %>
Update: So I think I solved my problem, or at least got my form view looking cleaner, by taking all the javascript out and stuffing it into application.js
(and wrote it up in jQuery just to try out something new).
The new form view looks like:
# app/views/label_sets/_form.html.erb
<%= form_for(@label_set) do |f| %>
# ...
<div class="field">
<%= label "label_sets", t('.label_set') %><br />
<%= select_tag("label_sets",
options_for_select(LabelSet::NAMES),
{ :include_blank => t('.new') }) %><br />
</div>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
# ...
<% end %>
The new application.js
looks like:
# public/javascripts/application.js
$(function() {
$('.new_label_set, .edit_label_set').submit(function() 开发者_C百科{
if ($('#label_set_name').attr('disabled') == true) {
$('#label_set_name').removeAttr('disabled');
}
});
$('#label_sets').change(function() {
if ($(this).val() == '') {
$('#label_set_name').val('');
$('#label_set_name').removeAttr('disabled');
} else {
$('#label_set_name').val($(this).val());
$('#label_set_name').attr('disabled', true);
}
});
});
The second approach is favoured over the older and previous rjs style code. Pretty much the second approach opens up much more chances of minimizing the javascript code by compressing it, converting it into tar.gz so that transport to client browsers are faster etc. Also look into How can I submit a value from another field on the page via link_to with Rails? thread also for more detail on the same issue.
精彩评论