Функция Unobtrusive-JS не запускается при удалении новых записей при использовании jQuery-ujs с Rails - PullRequest
0 голосов
/ 28 мая 2018

Rails: 5.2.0, Ruby: 2.4.1p111, Браузер: Chrome 66.0.3359.181, гем jquery-rails: 4.3.3, Turbolinks отключены.

Я слежу за этим AJAX на Railsс ненавязчивым учебником JS и достигли конца, но у меня странное поведение, которое я не могу понять.

Приложение использует UJS, чтобы позволить пользователю добавлять новые записи в конец списка через AJAX без необходимости обновлять всю страницу, как это обычно делает Rails.Добавление новых записей работает нормально, но когда я нажимаю «Удалить», функция JS в application.js не запускается, поэтому ничего не происходит, но когда я обновляю страницу, запись исчезает.Если я добавляю новую запись, обновляю страницу и затем пытаюсь удалить запись, запускается JS, и запись немедленно удаляется / удаляется из списка.

Веб-страница очень проста:

<!––  index.html.erb ––> 
<h1>Tutorials</h1>

<ul id=tutorials>
  <%= render @tutorials %>
</ul>

<%= form_with model: Tutorial.new, data: {'js-tutorial-form' => true} do |form| %>
  Title <%= form.text_field :title %><br>
  URL <%= form.text_field :url %><br>
  <%= form.submit %>
<% end %>

с небольшим частичным:

<!––  _tutorial.html.erb ––> 
<li data-js-tutorial-id=<%= tutorial.id %>>    
  <%= tutorial.title %> <%= link_to "Delete", tutorial, remote: true, method: :delete %>
</li>

все JS находится в файле application.js

$(document).ready(function() {
  $('[data-js-tutorial-form]').on("ajax:success", function(event, data, status, xhr){
    var tutorial = $(xhr.responseText).hide();
    $('#tutorials').append(tutorial);
    tutorial.fadeIn(2000);
  });

     $('[data-js-tutorial-id]').on("ajax:success", function(event, data, status, xhr){
    var tutorial_id = xhr.responseJSON.id;
    $('[data-js-tutorial-id=' + tutorial_id + ']').hide();

  }); 

});

единственный другой файл - это контроллер

class TutorialsController < ApplicationController

    def index
        @tutorials = Tutorial.all
    end

    def create
        @tutorial = Tutorial.new(params[:tutorial].permit(:title, :url))
        if @tutorial.save
                render partial: "tutorial", locals: {tutorial: @tutorial}
        end
    end

    def destroy
        @tutorial = Tutorial.find(params[:id])
        @tutorial.destroy
        render json: @tutorial
    end

end

Чего я не понимаю, так это того, что исходный код HTML идентичен до и после обновления страницы, но я подтвердил, используя инструменты разработчика Chrome, что $ ('[data-js-tutorial-id]')не вызывается до тех пор, пока страница не будет обновлена.Я использовал byugug в контроллере, чтобы подтвердить, что он правильно проходит.Есть идеи?

1 Ответ

0 голосов
/ 29 мая 2018

Ваша проблема в том, что слушатель JavaScript связан с тегом <li>, а не с реальной ссылкой.У слушателя никогда не было шанса выстрелить.

Лично я бы изменил метод destroy, зачем возвращать только что удаленный учебник?

def destroy
  @tutorial = Tutorial.find(params[:id])
  @tutorial.destroy
  render json: {success: true}
end

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

<!––  _tutorial.html.erb ––> 
<li>    
  <%= tutorial.title %> <%= link_to "Delete", tutorial, remote: true, method: :delete, "data-js-delete": tutorial.id %>
</li>

, что, конечно, требует изменения в JavaScript:

$('[data-js-delete]').on("ajax:success", function(event, data, status, xhr){
  $(event.target).closest('li').hide();
}); 
...