With each consecutive trigger, the AJAX form in Rails 4.2 submits to the server at an increasing rate

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>");

Answer №1

In order to prevent multiple instances of licences being initialized after the select request is complete, you can store the licence instance in a data property and only initialize it if it doesn't already exist on the form element:

$(document).on("ajaxSuccess", function() {
  $("form.edit_license, form.new_license").each(function(i, form) {
    var $form = $(form);
    var license = $form.data('license');
    if (!license) $form.data('license', new App.license());
  })
});

Additional tip: With Rails (or more specifically jquery-ujs), you can easily achieve select/AJAX behavior without extra effort! :)

If you include data-remote, data-url, and data-method attributes to your select element, jquery-ujs will handle the serialization and request for you. For example, with simple_form, you can try something like this:

<%= f.input :company do %>
  <%= f.select
    :company,
    options_from_collection_for_select(
      Company.sorted_by('company_name_asc'), 'id', 'company_name'
    ),
    { include_blank: false },
    data: {
      remote: true,
      method: 'get',
      url: addresses_path
    }
  %>
<% end %>

When the select option changes, jquery-ujs will make a GET request to

/addresses?company_id=:selected_id
where you can handle the response accordingly.

I hope this information proves useful!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for comparing URLs of the current active tab

Looking to create an adblocker specifically for a certain website. I have successfully implemented code that removes ads on the homepage, but it is still affecting other pages such as movie pages. This results in the deletion of the information section, i ...

Using the native functionality, submitting a razor form with JQuery AJAX in MVC6

Is there a specific method to submit a form using jQuery AJAX in MVC6 while still utilizing the Auto Binding functionality of ASP.NET MVC? In previous versions of MVC, one could use jquery.unobtrusive-ajax and simply utilize @using (Ajax.BeginForm("SaveDa ...

Create a setup page upon initial login using express.js

Currently, I am implementing Passport.js for user authentication on my express.js application. I aim to display a setup page upon the initial login of the user. Is it possible to achieve this using Passport? ...

Obtain the template as a string within Vue

Let's examine the scenario of having a single file component in Vue with the following structure: // Article.vue <template> <div> <h1>{{title}}</h1> <p>{{body}}</p> </div> </template> If w ...

Different boolean variable assigned to every item in v-for loop

I am working on creating a custom play/pause button for my audio elements, and here is how I have implemented it: <div v-for="(post, p) in post_list"> <!-- ... --> <!-- ... --> <!-- ... --> <v-avatar v-i ...

Connect to the Kendo dropdown list undefined

I am looking to automatically bind a model to a Kendo dropdown list. The model is retrieved from the server and can sometimes be undefined or a valid object. My problem arises when the value is undefined. In this case, Kendo selects the first item in the ...

What is the process for removing a range of keys from indexeddb?

I need help deleting keys that start with tracklist/RANDOM_STRING and 'songBook/RANDOM_String'. I attempted to do this using IDBKeyRange but I am struggling to understand how it works. The documentation I referred to was somewhat confusing: Mdn ...

Contrasting import and require methods

// script.js file; let x = 0; let updateValue = () => { x = 1; }; export { x, updateValue }; // script1.js import { x, updateValue } from './script.js'; updateValue(); console.log(x); // --> x = 1; however // script.js let x = 0; let ...

Uploading files in chunks using a combination of HTML, JavaScript,

I've been using a file chunking solution (although I can't recall its origin), but I've made some modifications to suit my requirements. Most of the time, the file uploads successfully; however, there are instances where an error occurs. U ...

We encountered a sudden termination of JSON data while parsing near '...w2BfLygJAO9ZBvYIqZTld'

Encountered an error when trying to initialize a new React App. command: $npx create-react-app yourblog Node --version v12.16.2 npx --version 6.14.4 Click here to view the error ...

A guide on calculating character count in a text area where certain characters are counted twice (javascript)

Is there a way to accurately count the characters in a textarea field, taking into account special characters like "é, è, €, ..." which should count as two characters? This is important for sending SMS messages where character limits are crucial, as so ...

JavaScript - If you change the properties of an object within an array, does it automatically set the array as needing an update?

If we were to imagine a scenario where there is an array containing 3 objects, and then I decide to access the second object by its index in order to modify one or more of its properties, what would happen? Would this modification mark the entire array a ...

React is throwing an error because it cannot access the property 'length' of an undefined value

TypeError: Cannot read property 'length' of undefined When I try to run my React app, I keep getting this error message from the compiler. What steps should I take to resolve this issue? request = (start,end) => { if(this.state.teams.lengt ...

Vue.js Conditional RoutingIn Vue.js, conditional routing allows

I'm currently facing a challenge where I want to display two different views for the same path based on the presence of a token in LocalStorage. While I could easily handle this logic within each view itself, I'm exploring the possibility of achi ...

Utilizing JavaScript for validation on an ASPX page within Visual Studio

After entering an email ID in a textbox, the email validation process is initiated. However, it seems that there is an issue where the entire function may not be executed properly. <head runat="server"> <title></title> ...

The Concept of Interface Segregation Principle within jQuery

Could someone provide a clear explanation of how this function operates using jQuery? Especially in reference to the response found here. It seems similar to the Single Responsibility Principle (SRP) in Object-Oriented Programming. What sets it apart? ...

Hide or eliminate SVG element

Can CSS or jQuery be used to remove or hide an SVG element? I am familiar with modifying div elements using CSS. For example: div[style="position: absolute; cursor: pointer; width: 207px; height: 95px; left: 513px; top: 0px; -webkit-transform-origin: ...

Implementing a personalized Angular filter with an indexOf condition

As a beginner in the world of computers, I am attempting to create a customized filter for an AngularJS application. My objective is to search through a string of integers (cultivos.age) and retrieve the item if the string meets the mes.age condition. I h ...

Integrate SVG directly into the three.js module to eliminate the need for an additional HTTP request

Currently, I am developing a small website that features a simple 3D animation. The model is extruded from an SVG file loaded using SVGLoader. My goal is to enhance the loading speed by including the SVG as text in my threejs code, eliminating the need for ...

Having trouble passing form data to the action method in MVC while using jQuery ajax?

Within my application, I am displaying a report that users can filter. Users input filter data and then click the 'Go' button. When the 'Go' button is clicked, I use jQuery to send the entire form to the controller action. My goal is to ...