Search code examples
jqueryruby-on-railsujs

Remote form opens all other remote forms on the page


I have a user dashboard controller with multiple remote forms inside the same view for the user to update misc attributes:

class CustomerDashboardController < ApplicationController
  def settings
  end
end
//settings.html.erb
<div class="info__item">
  <p class="info-item__heading">Name: <%= link_to "Edit", "", class: "info-edit__link", id: "user-edit__name", remote: true %></p>
</div>

<div class="info__item">
  <p class="info-item__heading">Email: <%= link_to "Edit", "", class: "info-edit__link", id: "user-edit__Email", remote: true %></p>
</div>

The jquery ujs triggers exist in a *.js.erb file, with it's name matching the appropriate action/view template that the forms are contained in:

//customer-dashboard/settings.js.erb
$('#user-edit__name').hide().after('<%= j render("user-edit-name-form") %>');
$('#user-edit__address').hide().after('<%= j render("user-edit-address-form") %>');

Each of the forms renders and updates the attributes correctly, However when clicking on a single link with remote: true, it renders every single form partial on the page simultaneously instead of just the single partial related to that link with unique id: ""


Solution

  • By @NM Pennypacker's suggestion, I came to a solution by skipping using remote: true altogether and just using Javascript to toggle the visibility of the multiple form partials instead.

    My javascript solution:

      allEditButtons = document.querySelectorAll('.info-edit__link');
    
      const showFormListener = event => {
        event.preventDefault();
        toggleAdjacentFormVisibility(event);
      };
    
      allEditButtons.forEach(element => {
        element.addEventListener('click', showFormListener);
      });
    
      function toggleAdjacentFormVisibility(event) {
        event.target.parentElement.nextElementSibling.classList.toggle(
          'info__is-not-visible'
        );
        event.target.parentElement.nextElementSibling.nextElementSibling.classList.toggle(
          'info__is-visible'
        );
      }
    

    The view:

      <div class="info__item">
          <p class="info-item__heading">Email: <%= link_to "Edit", "", class: "info-edit__link" %></p>
    
          <p class="info-item__info">
            <%= @user.email %>
          </p>
    
          <div class="info-item__form-container">
            <%= render ('user-edit-email-form') %>
       </div>
    
        </div>
    
      <div class="info__item">
          <p class="info-item__heading">Email: <%= link_to "Edit", "", class: "info-edit__link" %></p>
    
          <p class="info-item__info">
            <%= @user.phone %>
          </p>
    
          <div class="info-item__form-container">
            <%= render ('user-edit-phone-form') %>
          </div>
    
        </div>
    

    CSS:

      .info__is-visible {
        display: block;
      }
      .info__is-not-visible {
        display: none;
      }