Многоразовые удаленные модальные рельсы

Я пытаюсь создать многоразовый удаленный модальный. Идея заключается в создании контейнера модели и рендеринг содержимого с yield в него и рендеринг содержимого, когда это необходимо.

Примечание: весь код HTML будет записан в HAML. Я использую bootstrap-modal-rails gem для обработки моих модалов.

Модный макет контейнера (не частичный):

%div(class="modal" id="mainModal ajax-modal" tabindex="-1" role="dialog"){:'aria-labelledby'=>"mainModalLabel", :'aria-hidden'=>"true"}
  %div(class="c-modal__container")
    %div(class="c-modal__layout modal__content") 
      = yield

В моем application.html.haml у меня есть div, который определяет модальное расположение следующим образом:

-# ...
%div(id="modal-holder")

- unless params[:nojs]
  = javascript_include_tag 'desktop'

-# ...

Вот откуда моя проблема. У меня есть book controller, где пользователь может добавлять книги. У меня многоступенчатая регистрация, и мое действие new должно быть моим модальным. Когда пользователь нажимает ссылку New book, я загружаю новый модальный.

Моя ссылка New book:

= link_to "New book", new_book_path, class: "c-link--navbar", data: { modal: true }

CoffeeScript (переписанный в jQuery) для модального (этот код из в этой статье):

$(function() {
  var modal_holder_selector, modal_selector;
      modal_holder_selector = '#modal-holder';
      modal_selector = '.modal';
  $(document).on('click', 'a[data-modal]', function() {
    var location;
    location = $(this).attr('href');
    $.get(location, function(data) {
      return $(modal_holder_selector).html(data).find(modal_selector).modal();
    });
    return false;
  });
  return $(document).on('ajax:success', 'form[data-modal]', 

  function(event, data, status, xhr) {
    var url;
    url = xhr.getResponseHeader('Location');
    if (url) {
      window.location = url;
    } else {
      $('.modal-backdrop').remove();
      $(modal_holder_selector).html(data).find(modal_selector).modal();
    }
    return false;
  });
});

И теперь мой new action для yield, который будет загружен внутри моего удаленного модала:

= form_for(@book, remote: remote, html: {role: :form}, class: "c-form") do |f|
  -# Forms here...
  = f.submit "Add a new book", class: "c-btn"

Если информация пользователя верна, мой модальный будет перенаправлять пользователя на general action else, я хочу оставаться на той же странице и выпустить сообщение об ошибке, но проблема в том, что я не использую partial и автоматически перенаправляет меня на новую страницу с помощью new action.

Мой books_controller.rb:

class BooksController < ApplicationController
  respond_to :html, :json, :js
  ...

  def index
    @books = current_user.books
  end

  def new
    @book = current_user.books.build
    respond_modal_with @book
  end

  def create
    @book = current_user.books.build(book_params)

    if @book.save
      redirect_to general_book_path(@book), notice: "Saved."
    else
      flash.now[:notice] = "Something went wrong."
      render :new
    end
  end

  ...
end

Модальный ответчик:

class ModalResponder < ActionController::Responder
  cattr_accessor :modal_layout
  self.modal_layout = 'modal'

  def render(*args)
    options = args.extract_options!
    if request.xhr?
      options.merge! layout: modal_layout
    end
      controller.render *args, options
  end

  def default_render(*args)
    render(*args)
  end

  def redirect_to(options)
    if request.xhr?
      head :ok, location: controller.url_for(options)
    else
      controller.redirect_to(options)
    end
  end
end

Я попытался добавить что-то вроде

respond_to do |format|
  format.html
  format.json { render json: @book }
end

к моему методу create, но он не работает и перенаправляет меня на новую страницу. Кроме того, я уже задал аналогичный question, и я заметил, что мой код JavaScript работает на отдельной странице. Пока я понимаю, что проблема связана с моей страницей удаленных модальных действий. Может кто-то, пожалуйста, помогите мне разобраться, как оставаться на той же странице, когда пользователь ввел неправильный ввод и включил мой javascript?

Ответы

Ответ 1

TBH, что абстрактное решение, которое напрямую не связано с вашим вопросом, работает хотя (bootstrap + jq, на основе производственного кода)

Coffe script

$.showModal = (title, body) ->
    $("#modal").find(".modal-title").html(title)
    $("#modal").find(".modal-body").html(body)
    $("#modal").modal("show")
$("#modal").find(".modal-submit").click () ->
    $("#modal").find("form").submit()

Html - типичный загрузочный модальный

<div id="modal" class="modal" tabindex="-1" role="dialog">
  <div class="modal-dialog modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title"></h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="<%= t :close %>" title="<%= t :close %>">
          <span aria-hidden="true"></span>
        </button>
      </div>
      <div class="modal-body">
        <p></p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-danger" data-dismiss="modal"><%= t :close %></button>
        <button type="button" class="btn btn-success modal-submit"><%= t :save %></button>
      </div>
    </div>
  </div>
</div>

new.js.erb или другой вид рельсов

$.showModal(
    "<%= escape_javascript t :edit_comment %>",
    "<%= escape_javascript(render 'form', :comment => @comment) %>"
);

ссылка для открытия модального

<%= link_to t(:new), [:new, comment], :remote => true, class: "btn" %>

Вероятно, вы хотели бы использовать свой собственный запрос ajax - этот ничего не сделал бы в случае ошибки сервера/таймаута