Добавление ajax для удаления объекта — Rails

#javascript #ruby-on-rails #ajax #rspec

#javascript #ruby-on-rails #ajax #rspec

Вопрос:

В настоящее время у меня есть простая form_for, которая удаляет объект. Сейчас это статическая страница, которая обновляется каждый раз, когда объект удаляется. Мы получаем запрос клиента, который хотел бы, чтобы индексная страница удаляла объект без обновления страницы. Очевидно, что ajax может решить эту проблему, но у меня очень ограниченный опыт работы с javascript. Если бы кто-нибудь мог указать мне правильное направление, я был бы очень признателен. Вот мой код для ясности.

ФОРМА

Это форма, которая выводит модальный при нажатии delete.

  <%= link_to 'Delete', delete_snitch_path(snitch), rel: 'modal:open',
   data: { tooltip: "Delete" },
   class: 'icon icon-delete delete', title: "Delete #{snitch.name}" %>
  

  <%= form_for @snitch, html: { class: "form-actions", method: 'delete' } do |form| %>
 <span class="button-text"><%= link_to 'NO WAY!', home_base_url_or_default(root_path), rel: "modal:close" %></span>
 <input type="submit" class="button button--modal" value="Yes, delete it.">
 <% end %> 
  

Контроллер

   def destroy
    DestroySnitch.perform(snitch: @snitch)

    respond_to do |format|

      format.html do
        redirect_to snitches_path, notice: "Snitch was successfully deleted."
      end

      format.json do
        render json: @snitch.all
      end

    end
  end  
  

Вид

 <table class="snitch-list">
  <%= render partial: 'snitch', collection: @presenter.snitches %>
</table>
  

ТЕКУЩИЙ JS (НЕ РАБОТАЕТ, ОЧЕВИДНО)

 $('ajax').bind('ajax:success', function() {
    $(this).closest('tr').fadeOut();
});
  

Весь частичный стукач

   <tbody>
  <tr class="<%= snitch.classes %>">
    <td>
        <%= link_to "<span class='icon led'></span><span>#{snitch.name}</span>".html_safe, snitch_path(snitch), class: "name"%>
    </td>
    <td class="interval"><span class="vspace"><%= snitch.interval %></span></td>
    <td class="last-checked">
      <span class="vspace">
        <% if snitch.source.checked_in_healthy_at %>
          <span data-tooltip="Checked in healthy at UTC(<%= snitch.source.checked_in_healthy_at.to_i %>) || LOCAL(<%= snitch.source.checked_in_healthy_at.to_i %>)">
            Last seen <strong><%= snitch.checked_in_healthy_at(title: nil) %></strong>
          </span>
        <% else %>
          <strong><%= snitch.checked_in_healthy_at %></strong>
        <% end %>
      </span>
    </td>
    <td class="snitch-controls" data-icons="<%= snitch.pauseable? ? "5" : "4" %>">
      <%= render 'menu', snitch: snitch %>
      <nav class="snitch-states" >
        <% if snitch.pauseable? %>
          <%= link_to 'Pause', pause_snitch_path(snitch), class: 'icon icon-pause pause',
            data: { tooltip: "Pause" },
            rel: "modal:open" %>
        <% end %>

        <%= link_to 'Delete', delete_snitch_path(snitch), rel: 'modal:open',
          data: { tooltip: "Delete" },
          class: 'icon icon-delete delete', title: "Delete #{snitch.name}" %>
        </nav>
    </td>
  </tr>
</tbody>
  

У меня нет никакого javascript, и я начинаю эту историю только сейчас, но я уже запутался во время поиска в Google. кроме того, есть ли хороший способ протестировать ajax с помощью Rspec и Capybara?

Комментарии:

1. Чтобы ответить на этот вопрос, мне нужен код для модального, который появляется с запросом подтверждения. Ajax будет привязан к этой кнопке, а не к кнопке в форме. Можете ли вы опубликовать модальный код? Также было бы полезно иметь код для страницы, на которой находится этот элемент, таким образом, код для скрытия или удаления div также может быть в ответе.

2. Обновлено @RockwellRice. Дайте мне знать, если вам нужно больше

3. Я не вижу html для модального, похоже, кнопка в форме открывает модальный правильный? Фактическое удаление произойдет при нажатии кнопки внутри модального, так что это кнопка, которую мне нужно увидеть, чтобы написать код. Кроме того, укажите код внутри этой части, мне нужно увидеть фактический div, который будет удален или скрыт.

Ответ №1:

Прикрепите класс к кнопке (мой ajax здесь использует «delete-snitch»), который подтверждает удаление в модальном.

Добавьте свойство «data-snitch-id» к этой кнопке. Вам понадобится идентификатор объекта, чтобы удалить нужный объект.

(Это необходимо добавить к кнопке в модальном, на которую нажимается.)

 <button class="delete-snitch ...any other classes..." data-snitch-id="<%= snitch.id %>"> ... </button>
  

В вашем файле javascript поместите что-то вроде приведенного ниже

   $(document).on('click','.delete-snitch', function() {

    var snitchID = $(this).attr('data-snitch-id'); 
    $.ajax({
        type: 'DELETE',
        url: '/snitch/'   snitchID,
        success: function(){
            $('#tr-for-snitch-'   snitchID).fadeOut;
        }
    });
});
  

Вы должны убедиться, что в свойстве data-snitch-id есть идентификатор, прежде чем это сработает.

Добавьте идентификатор в tr, который вы пытаетесь удалить.

 <tr id="tr-for-snitch-<%=@snitch.id%>" class="<%= snitch.classes %>">
  

Комментарии:

1. Спасибо за помощь. Куда мне поместить remote: true?

2. Я не думаю, что вам это понадобится, javascript, который я опубликовал, обрабатывает запрос ajax.

3. Ах, я понимаю. То же самое относится и к элементу «response_to» в контроллере?

4. Содержимое в контроллере оставить как есть

5. Просто примечание, если вы подключаете это к кнопке отправки, вам нужно настроить первую строку кода javascript следующим образом (обратите внимание на e в скобках): «$(document).on(‘click’,’.delete-snitch’, function (e) { «а затем прямо под этой строкой поместите это » e.preventDefault(); »

Ответ №2:

Вот несколько шагов, потому что у меня нет всего вашего исходного кода с представлениями и всем остальным.

  1. Создайте html-кнопку с определенным классом.
  2. Добавьте прослушиватель ( $('.button-class').click(sendDeleteRequest(e)) ) на кнопку, отправляющую запрос к вашему API удаления. https://api.jquery.com/click / документация, если она вам нужна.
  3. При успешном выполнении 200 ответа от вашего API удаления удалите элемент.
  4. Чтобы удалить элемент, выберите с помощью jquery. ie. $('.class-of-object).remove();
  5. При сбое window.alert("Oops, that didn't work") или window.reload()