JQuery for dynamic updates in Rails

Posted as an aide memoire because I’ll forget what project I’ve used it in and how to do it; I’m a part-time RoR coder, not my day job, though the stuff I am writing is important to other people’s operational work.

To create a select dropdown of items when another form element is changed.

Include some JQuery gems (I suspect this is where all the hard work is done and I’m just adding the easy stuff),

# Use jquery as the JavaScript library
gem 'jquery-rails'
gem 'jquery-modal-rails'
gem 'jquery-tokeninput-rails'

It could pay to be careful with this because of October 2014, version 5 of jquery-rails is out and comes with a lot of changes and breakage. Another post on this soon.

Declare a variable as an anonymous function call (closure). Then register a handler for the change event with another closure. Capture the selected value of the form element that triggers the event (perhaps with a sensible default), issue an JSON request to a controller method and loop through each of the returned values and append them to the select list. Finally register the closure variable to load on the page.

var ready = function() {
 $("#model_name_trigger_id").change(function() {
 var sd = $("#model_name_trigger_id option:selected").val();
 if (!sd) {
 sd = 1;
 };
 $("#model_name_field_id").html('');
 // make a GET call and replace the content
 // If not using a nested model, use,
 // $.getJSON( '/controller_name/list_of_items.json', function(data) {
 $.getJSON( '/controller_name/' + sd + '/list_of_items.json', function(data) {
 for (var x in data) {
 $("#model_name_field_id").append($('<option></option>').val(data[x].id).html(data[x].label));
 };
 });
 });
};
$(document).ready(ready);
$(document).on('page:load', ready);

Define a route for the JSON request to the controller

match 'controller_names/:id/list_of_items', :to => 'controller_names#list_of_items', :via => [:get, :post]

This will capture the JQuery ‘sd’ variable as an :id param in the controller for the nested model
but remove the ‘:id’ if not just using a single model.

Write a method in a rails controller

def list_of_items
  // Grab the params submitted in the JSON request
  i = params[:id]
  @items = Item.nested_model_scope(i)
  respond_to do |format|
    format.html
    format.json { render json: @items } 
  end
end

Then prepare a JSON template in the views,

json.array! items do |item|
  json.extract! item, :id, :label
end

This might not be 100% accurate in terms of the names but it’s enough to the serve the purpose of reminding me of the what I need to include when I do this next time.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s