Модальный загрузчик в Rails продолжает отображать первую запись

#ruby-on-rails #twitter-bootstrap #modal-dialog

#ruby-on-rails #twitter-bootstrap #модальный диалог

Вопрос:

Когда я нажимаю на представление в модальном режиме, оно продолжает отображать только первую запись. Даже если я нажму на вторую запись, она все равно отобразит первую. Ниже показано, как я реализовал link_to переключение на модальное поле под названием myModal.

 <%= link_to 'View in Modal', "#", data: {toggle: "modal", target: "#myModal"} %>
      <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">amp;times;</button>
            <h4 class="modal-title" id="myModalLabel">Test</h4>
          </div>
          <div class="modal-body">
            <span class="note"><%= raw(usernote.note) %></span>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
            <button type="button" class="btn btn-primary">Save changes</button>
          </div>
        </div>
      </div>
  </div>
 

введите описание изображения здесь

Ответ №1:

Проблема

Я предположил, что вы сделали что-то вроде:

 <% @usernotes.each do |usernote| %>
 <%= link_to ... %>
 // code of modal associated to the usernote
<% end %>
 

Проблема в том, что вы использовали один и тот же идентификатор html для всех модалов ( #myModal ) . Помимо того, что дублирование идентификаторов не соответствует W3C, это является причиной проблемы.

Когда вы нажмете на одну из ссылок, откроется первая модальная с #myModal идентификатором (который является модальным для первой записи).

Итак, как исправить проблему?

Простой способ: один модальный на заметку пользователя

Один из способов, простой способ, — использовать разные идентификаторы для всех модалов. Например:

 <%= link_to ... data: {toggle: "modal", target: "#modalForUserNote#{ usernote.id }"} %>
  <div id="modalForUserNote<%= usernote.id %>" ...>
  // ....
 

Но этот способ не самый лучший: вы просто создаете один модальный для каждой заметки пользователя… Если у вас 1000 пользовательских заметок, вы сгенерируете 1000 модалов в своем html… Это, очевидно, довольно плохо…

Другой способ: обратный вызов javascript

Другой способ сделать это — создать только один модальный файл и отредактировать его содержимое с помощью некоторого кода Javascript.

Примером кода может быть:

html code

   // the modal code

  <% @usernotes.each do |usernote| %>
    <% link_to ..., data: {toggle: "modal", target: "#modal"}, 'data-usernoteid' => ..., 'data-usernotedata' => ... %>
  <% end %>
 

javacript code (using jQuery)

   $('.modalLink').on('click', function() {
    $('#modal #idOfTheUserNote').html($(this).data('usernoteid'));
    // ...
  });
 

Вы можете отметить использование атрибутов данных.
Атрибуты данных могут быть заменены AJAX-запросом к вашему приложению Rails, который вернет данные JSON.

Другой способ: запрос AJAX

Последний способ сделать это — запросить ваше приложение Rails с помощью вызова Ajax. Ваше приложение отобразит представление Javascript (код будет отправлен в ваш браузер и оценен).

Это можно просто сделать, используя remote: true опцию в вашем link_to (rails сам обработает запрос ajax.

Следующий код может сделать трюк:

html code

   // the modal code

  <% @usernotes.each do |usernote| %>
    <% link_to 'text', some_action(usernote), data: {toggle: "modal", target: "#modal"}, remote: true %>
  <% end %>
 

controller code

    def some_action
     @usernote = Usernote.find_by_id(param[:id])
   end
 

view to render: for example usernote/some_action.js.erb

    $("#modal #modalIdOfTheUsernote").html("<%= @usernoed.id %>");
 

Каков наилучший способ сделать это?

Очевидно, не первую.

Выбор между двумя другими зависит только от того, что вы хотите сделать:

  • Для обновлений в реальном времени запрос AJAX может быть лучше. Но вы можете получить некоторую задержку, потому что вам нужно дождаться ответа сервера.
  • В противном случае атрибуты данных достаточно хороши.

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

1. Ответ может занять некоторое время… особенно, когда английский не является родным языком.

Ответ №2:

здесь 3 варианта:

  1. создайте один модальный для каждой записи — худшее, что вы можете сделать
  2. используйте атрибуты данных для обновления содержимого модального
  3. используйте действие ajax, в котором вы обновите содержимое модала и откроете модал с помощью $('#myModal').modal('show') http://getbootstrap.com/javascript/#modals-usage

1. создайте один модальный для каждой записи

 <% @usernotes.each do |usernote| %>
  <%= link_to 'View in Modal', "#", data: {toggle: "modal", target: "#myModal_<%= usernote.id %>"} %>
  <div class="modal fade" id="myModal_<%= usernote.id %>" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
    ....
    <span class="note"><%= raw(usernote.note) %></span>
    ....
  </div>
<% end %>
 

2. используйте атрибуты данных для обновления содержимого модального

 <% @usernotes.each do |usernote| %>
  <%= link_to 'View in Modal', "#", data: {usernote: usernote.note}, class: 'user_note_modal' %>
<% end %>

 $('.user_note_modal').on('click', function() {
    $('#myModal span.note').html($(this).data('usernote'));
    $('#myModal').modal('show');
  });
 

p.s. зачем использовать .modal('show') ? просто убедитесь, что вы сначала обновили содержимое модала, а затем отобразили его.


3. используйте действие ajax — при условии, что ваше имя ресурса UserNote и у вас есть user_notes_controller с show действием:

 <% @usernotes.each do |usernote| %>
  <%= link_to 'View in Modal', usernote_path(usernote), data: {toggle: "modal", target: "#myModal"}, remote: true %>
<% end %>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-body">
    <span class="note"></span>
  </div>
</div>
 

нажатие на одну ссылку вызовет событие ajax, которое будет ожидать шаблон show.js.erb, в котором вы обновите содержимое модала, а затем отобразите его:

 app/views/user_notes/show.js.erb

$('.modal-body span.note').html('<%= j(render @usernote.note) %>');
$('#myModal_').modal('show');