Reputation: 35149
Assume I have a vanilla form containing a selection list and a submit button:
<%= form_for(@report :url => report_path) do |f| %>
<%= f.select(:sort_by, options_for_select(Report.SORT_OPTIONS, @report.sort_by)) %>
<%= f.submit 'sort' %>
<% end %>
Works fine, except that the user has to first make a selection and then click 'sort'. What I'd really like is to have the action triggered when the user makes a selection and to ditch the 'sort' button altogether. This feels like a perfect use case for unobtrusive jQuery.
So [based on responses from @Dennis and @ethan below], before this form_for
I added:
<%= javascript_include_tag(:defaults) %>
<script type="text/javascript">
$(document).ready(function() {
var $select = $('#report_sort_by'),
$form = $select.closest('form');
// $('[type="submit"]', $form).attr('type', 'hidden'); // gives error
$('[type="submit"]', $form).hide(); // works
$select.change(function() { $form.submit(); });
});
</script>
So is it considered right to plunk javascript right into the .html.erb file? Or is it better to put this in a separate .js file, and if so, what are the conventions for paramaterizing and naming the .js file?
For a few reputation points, can someone show me and all the other tyros how to do this?
Upvotes: 0
Views: 1433
Reputation: 156
Rails will stringify the object & property you're using, so the select menu would have id="report_sort_by"
. Which means you could use:
var $select = $('#report_sort_by'),
$form = $select.closest('form');
// preserve the button's name/value attributes, if Rails has assigned them
$('[type="submit"]', $form).hide();
$select.change(function() {
$form.submit();
});
If you want to include this code in a robust, unobtrusive way, you could make a file called maybe MyProject.Report.js and put this code in it:
if (!MyProject) var MyProject = {};
MyProject.Report = {
init: function() {
var $select = $('#report_sort_by'),
$form = $select.closest('form');
// preserve the button's name/value attributes, if Rails has assigned them
$('[type="submit"]', $form).hide();
$select.change(function() {
$form.submit();
});
}
}
Then in your .erb file (at the bottom, after the form) you could add <script type="text/javascript">MyProject.Report.init();</script>
and then, of course, add the javascript_include_tag
to include the JS file itself.
There's a bunch of different ways you could do your namespacing & encapsulation. The MyProject.Report
object that I describe above has the chief advantage of being incredibly straightforward. As your code grows, you just add new functionality inside the MyProject.Report
object like:
MyProject.Report = {
init: function(options) {
// some event handlers, maybe
this.complication(null, null, options.data);
this.reusable(options.bgcolor);
},
complication: function(a, b, c) {
// stuff that's tough to look at
this.reusable(b);
},
reusable: function(q) {
// code that's used multiple places
}
}
And then you basically hack away at that until you're knowledgeable enough to decide whether you need a framework like backbone.js for a given project :)
Upvotes: 2
Reputation: 32598
I'm not familiar with Ruby-on-Rails, so you may have to change the selectors but the general idea is:
$("#formId input[type='submit']").hide(); //Make the submit button invisible
$("#formId select.selectClass").change( function() {
$(this).closest("form").submit(); //Trigger the submit event on the parent form.
});
:html => {:id => 'formId', :method => :put }
Upvotes: 1