When I select a company from the dropdown list in a form, it triggers an update in another dropdown list for addresses through an AJAX request. The address options are successfully updated each time.
However, I noticed that when I switch between companies, the number of times the AJAX request is sent increases exponentially - starting with 1, then 2, 4, 8, and so on. This is not ideal...
I've been striving to organize my JavaScript following Brandon Hilkert's advice on organizing javascript.
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html lang="en">
<head>
<%# Disables turbolinks caching of pages, to allow smooth animations %>
<meta name="turbolinks-cache-control" content="no-preview">
<meta name="viewport" content="width=device-width, initial-scale=1">
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= csrf_meta_tags %>
<%= favicon_link_tag 'logos_and_banners/ecl_logo.png' %>
<title>Environmental Concern Ltd - Your future in our hands.</title>
<%# Geocompete JQuery plugin %>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?key=AIzaSyDfo9YlYY6BnemhdpDMlQbo6li3RyRYO-0&libraries=places"></script>
<%= render partial: 'shared/flash' %>
<%= render 'shared/navigation/navigation' %>
<%# console %>
</html>
app/views/licenses/_form.html.erb
<%= simple_form_for([@company, @license], remote: true, html: {role: 'form'}) do |f| %>
<%# errors will be loaded here via AJAX %>
<div id="form-errors" class="alert alert-danger collapse"></div>
<form role="form">
<div class="form-inputs">
<%= f.association :company,
collection: Company.sorted_by('company_name_asc'),
label_method: :company_name,
value_method: :id,
include_blank: false %>
<%= f.association :address,
collection: @company.addresses.sorted_by('site_name_asc'),
label_method: :site_name,
value_method: :id,
include_blank: true %>
<span class="help-block">
Certain License types are related to a specific Address, others are only linked to the Company.
</span>
<%= f.input :license_type,
collection: License::ALL_VALID_LICENSE_TYPES %>
<%= f.input :license_name, as: :hidden%>
<%= f.input :license_no %>
<%= f.input :expiry_date,
as: :string,
input_html: {
data: {
provide: 'datepicker', date_format: 'yyyy-mm-dd'
}
}%>
</div>
<%= render partial: 'shared/edit_new/save_button', locals: {model_name: find_model_name_for_view(@license)} %>
</form>
<% end %>
app/assets/javascripts/application.js
//= require jquery
//= require jquery.turbolinks
//= require jquery_ujs
//= require bootstrap-sprockets
//= require cocoon
//= require turbolinks
//= require data-confirm-modal
//= require jquery.geocomplete
//= require bootstrap-datepicker/core
//= require underscore
//= require gmaps/google
//
//= require init
//= require licenses/app.form.js
app/assets/javascripts/init.js
window.App || (window.App = {});
// Define init function on the App object
App.init = function(){
// Bootstrap tooltips. Must be manually enabled.
$(function () {
$('[data-tooltip="true"]').tooltip();
})
};
// Call the init function on every page transition.
// $(document).ready functions don't fire with turbolinks
$(document).on("turbolinks:load", function() {
return App.init();
});
app/assets/javascripts/licenses/app.form.js
App.license = (function() {
function licensesFormBehaviour() {
//Update address select based on Company choice
$('select#license_company_id').change(function() {
return $.ajax({
url: 'addresses',
type: 'GET',
dataType: 'script',
data: {
company_id: $("select#license_company_id option:selected").val()
},
error: function(jqXHR, textStatus, errorThrown) {
return console.log("AJAX Error: " + textStatus);
}
});
});
// Several other unrelated methods, which function fine.
// I've omitted them to make the code block shorter.
return licensesFormBehaviour;
})();
$(document).on("ajaxSuccess", function() {
//Licenses form only
if (!($("form.edit_license").length > 0) && !($("form.new_license").length > 0) ) {
return;
}
//invoke
var license = new App.license();
return license;
});
Thanks for taking the time to review this. Patrick.
Edit:
Response, requested by fanta.
AJAX response
// Within the append() I've omitted around 30 additional <option> tags, for readability.
$("#license_address_id").empty().append("<option value=\"\"></option><option value=\"197\">Berge Knolls<\/option>");