Search code examples
ruby-on-railsrubyruby-on-rails-7

Rails version 7.1.2: Js stop working when validation fails and controller send 422 status


I upgraded my app from 5.2 to 7.1.2, later I used turbolinks and after validation, it was working fine. After upgrading I am using Turbo and my javascript stops working when validation fails.

Here is my code snipped for reference: My controller:

# POST /admins/coupons
# POST /admins/coupons.json
def create
 @admins_coupon = Coupon.new(admins_coupon_params)
 @admins_coupon.admin = current_admin if current_admin.present?
 respond_to do |format|
   if @admins_coupon.save
     format.html { redirect_to admins_coupons_url, notice: 'Coupon ajouté avec succès.' }
     format.json { render :show, status: :created, location: @admins_coupon }
   else
     format.html { render :new, status: :unprocessable_entity }
     format.json { render json: @admins_coupon.errors, status: :unprocessable_entity }
   end
 end
end

Here is my Form:

<%= form_with(model: admins_coupon, url: url, scope: admins_coupon, local: true, data: {turbo: false}) do |form| %>
 <% if admins_coupon.errors.any? %>
   <div class='notification is-danger'>
     <ul>
       <% admins_coupon.errors.messages.each do |attr, msg| %>
         <li><%= t("activerecord.attributes.plan.#{attr}") %> 
           <%= msg.first %> </li>
       <% end %>
     </ul>
   </div>
 <% end %>

 <div class="columns">
   <div class="column">
     <div class="field">
       <%= form.label :code, class: 'label' %>
       <%= form.text_field :code, required: true, class: 'input', autofocus: true %>
     </div>
   </div>
   <div class="column">
     <div class="field">
       <%= form.label :description, class: 'label' %>
       <%= form.text_field :description, class: 'input' %>
     </div>
   </div>
   <div class="column">
     <div class="field">
       <%= form.label :redemption_limit, class: 'label' %>
       <%= form.number_field :redemption_limit, min: 0, required: true, class: 'input' %>
     </div>
    </div>
  </div>
<%end%>

Here my JS:

  document.addEventListener("turbo:load", function() {
    initializeBulmaCalendarPicker();
  });

  window.initializeBulmaCalendarPicker = function() {
    var datePickers = bulmaCalendar.attach('[type="date"]', {
      overlay: true,
      lang: 'fr',
      // dateFormat: 'mm-dd-yyyy'
      // dateFormat: 'yyyy-mm-dd'
    });
  }

The first time it is working fine, validation errors show correctly. browser screenshot

But after validation failed my js did not work, and the calendar picker stopped working where I am doing wrong. Any help would be appreciated, Thanks in advance.


Solution

  • It's likely that when a form submission fails validation and the form is re-rendered and the JavaScript (in your case, the Bulma calendar picker) is not being re-initialized. Partial page updates triggered by Turbo don't automatically re-run the JS initialized on the first page load.

    My guess is that the JavaScript components (like the Bulma calendar picker) are not re-initializing after a form submission fails validation and the form is re-rendered by Turbo.

    Try re-initialize your JavaScript components after Turbo renders the form. To do this you'd need to listen for Turbo-specific events that fire after form submission or page update. In your JS, you could try modify the event listener from turbo:load to turbo:submit-end or another appropriate Turbo event. This will ensure your JS re-initializes every time Turbo updates the form.

    You could try something like this:

    document.addEventListener("turbo:submit-end", function(event) {
      if (event.target.id === 'your_form_id') {  // Replace with your actual form ID
        initializeBulmaCalendarPicker();
      }
    });
    
    function initializeBulmaCalendarPicker() {
      var datePickers = bulmaCalendar.attach('[type="date"]', {
        overlay: true,
        lang: 'fr',
      });
    }