How to implement dependent dropdowns in Rails 4 with an unobtrusive jQuery script?
class SpecializationType < ActiveRecord::Base
# FIELDS
# RELATIONS
has_many :specializations
# TRIGGERS
# VALIDATIONS
validates :name, :presence => true
validates :description, :presence => true
# SCOPES
# OTHER
def to_s
name
end
end
class Specialization < ActiveRecord::Base
# FIELDS
# RELATIONS
belongs_to :specialization_type
has_and_belongs_to_many :users
# TRIGGERS
# VALIDATIONS
validates :name, :presence => true
validates :description, :presence => true
validates :specialization_type, :presence => true
# SCOPES
# OTHER
def to_s
name
end
end
in views
<%= form_tag users_path, {:method => :get, :class => "users_search_form"} do %>
<%= select_tag :specialization_type_id, options_from_collection_for_select(SpecializationType.all, "id", "name"), :prompt => "Select a specialization type" %>
<%= select_tag :specialization_id, options_from_collection_for_select([], "id", "name"),
"data-option-dependent" => true,
"data-option-observed" => "specialization_type_id",
"data-option-url" => "/specialization_types/:specialization_type_id:/specializations.json",
"data-option-key-method" => :id,
"data-option-value-method" => :name %>
<br/>
<%= submit_tag "Cerca" %>
<% end %>
In particular:
“data-option-dependent” => true, indicates that this depends on a dropdown dropdown father
“data-option-observed” => “specialization_type_id”, specifies the id of the dropdown to be monitored. If its value changes, we’ll trigger the request to the server
“data-option-url” => “/specialization_type/:specialization_type_id:/specializations.json” is the url that we are going to call on the server. The script will replace :specialization_type_id: the id of the selected item in the dropdown father.
“data-option-key-method” => :id, indicates that we’ll use the ID field of the json returned by the server as attribute “key” for < option >
“data-option-value-method” => :name, indicates that we’ll use the NAME field in the json returned by the server as attribute “value” of < option >
Let’s add this jQuery script in the application.js file, in order to handle all dependent dropdown of our code
jQuery(document).ready(function () {
$('select[data-option-dependent=true]').each(function (i) {
var observer_dom_id = $(this).attr('id');
var observed_dom_id = $(this).data('option-observed');
var url_mask = $(this).data('option-url');
var key_method = $(this).data('option-key-method');
var value_method = $(this).data('option-value-method');
var prompt = $(this).has('option[value=]').size() ? $(this).find('option[value=]') : $('<option value=\"\">').text('Select a specialization');
var regexp = /:[0-9a-zA-Z_]+:/g;
var observer = $('select#' + observer_dom_id);
var observed = $('#' + observed_dom_id);
if (!observer.val() && observed.size() > 1) {
observer.attr('disabled', true);
}
observed.on('change', function () {
observer.empty().append(prompt);
if (observed.val()) {
url = url_mask.replace(regexp, observed.val());
$.getJSON(url, function (data) {
$.each(data, function (i, object) {
observer.append($('<option>').attr('value', object[key_method]).text(object[value_method]));
observer.attr('disabled', false);
});
});
}
});
});
});
routes ---> 1
get "specialization_types/:specialization_type_id/specializations" => "application#specializations", :as => "specializations", :format => :json
def specializations
specialization_type = SpecializationType.find(params[:specialization_type_id])
respond_to do |format|
format.json { render :json => specialization_type.specializations }
end
end
class SpecializationType < ActiveRecord::Base
# FIELDS
# RELATIONS
has_many :specializations
# TRIGGERS
# VALIDATIONS
validates :name, :presence => true
validates :description, :presence => true
# SCOPES
# OTHER
def to_s
name
end
end
class Specialization < ActiveRecord::Base
# FIELDS
# RELATIONS
belongs_to :specialization_type
has_and_belongs_to_many :users
# TRIGGERS
# VALIDATIONS
validates :name, :presence => true
validates :description, :presence => true
validates :specialization_type, :presence => true
# SCOPES
# OTHER
def to_s
name
end
end
in views
<%= form_tag users_path, {:method => :get, :class => "users_search_form"} do %>
<%= select_tag :specialization_type_id, options_from_collection_for_select(SpecializationType.all, "id", "name"), :prompt => "Select a specialization type" %>
<%= select_tag :specialization_id, options_from_collection_for_select([], "id", "name"),
"data-option-dependent" => true,
"data-option-observed" => "specialization_type_id",
"data-option-url" => "/specialization_types/:specialization_type_id:/specializations.json",
"data-option-key-method" => :id,
"data-option-value-method" => :name %>
<br/>
<%= submit_tag "Cerca" %>
<% end %>
In particular:
“data-option-dependent” => true, indicates that this depends on a dropdown dropdown father
“data-option-observed” => “specialization_type_id”, specifies the id of the dropdown to be monitored. If its value changes, we’ll trigger the request to the server
“data-option-url” => “/specialization_type/:specialization_type_id:/specializations.json” is the url that we are going to call on the server. The script will replace :specialization_type_id: the id of the selected item in the dropdown father.
“data-option-key-method” => :id, indicates that we’ll use the ID field of the json returned by the server as attribute “key” for < option >
“data-option-value-method” => :name, indicates that we’ll use the NAME field in the json returned by the server as attribute “value” of < option >
Let’s add this jQuery script in the application.js file, in order to handle all dependent dropdown of our code
jQuery(document).ready(function () {
$('select[data-option-dependent=true]').each(function (i) {
var observer_dom_id = $(this).attr('id');
var observed_dom_id = $(this).data('option-observed');
var url_mask = $(this).data('option-url');
var key_method = $(this).data('option-key-method');
var value_method = $(this).data('option-value-method');
var prompt = $(this).has('option[value=]').size() ? $(this).find('option[value=]') : $('<option value=\"\">').text('Select a specialization');
var regexp = /:[0-9a-zA-Z_]+:/g;
var observer = $('select#' + observer_dom_id);
var observed = $('#' + observed_dom_id);
if (!observer.val() && observed.size() > 1) {
observer.attr('disabled', true);
}
observed.on('change', function () {
observer.empty().append(prompt);
if (observed.val()) {
url = url_mask.replace(regexp, observed.val());
$.getJSON(url, function (data) {
$.each(data, function (i, object) {
observer.append($('<option>').attr('value', object[key_method]).text(object[value_method]));
observer.attr('disabled', false);
});
});
}
});
});
});
routes ---> 1
get "specialization_types/:specialization_type_id/specializations" => "application#specializations", :as => "specializations", :format => :json
def specializations
specialization_type = SpecializationType.find(params[:specialization_type_id])
respond_to do |format|
format.json { render :json => specialization_type.specializations }
end
end
Comments
Post a Comment