可重复使用的远程模态框Rails

15

我正在尝试创建一个可重用的远程模态框。想法是创建一个模态框容器,并使用 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 }

使用jQuery重写的CoffeeScript代码,用于模态框(来自该文章):

$(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;
  });
});

现在,我的新操作是为了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”,否则我希望停留在同一页上并闪现错误消息,但问题是我没有使用部分页面,并且它会自动重定向我到一个新页面,其中包含“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方法中添加代码,但它不起作用,并且仍然将我重定向到新页面。此外,我已经提出了一个类似的问题,我注意到我的JavaScript代码可以在单独的页面上正常工作。只要我理解正确,问题应该出在远程模态操作页面上。请问有谁能帮助我找出如何在用户输入错误时保持在同一页上并开启我的javascript?


你好。我查看了你的Github个人资料,这不是一个开源项目吗?如果你让我fork你的项目,那么通过调试很可能可以轻松找到解决方案,否则我需要更深入地了解。 - Fabrizio Bertoglio
@FabrizioBertoglio 你好,我会在接下来的一两个小时内创建一个新项目,并在评论区通知你!非常感谢你的帮助和时间! - Anton S.
@fabrizio:你有发现控制器上的任何错误吗? - plonknimbuzz
1
我仍在调查您的SO帖子。您从未得到问题的答案的原因是您没有正确地书写它们。您的问题包含太多信息,从某种角度来看它非常广泛。我的建议是尝试将您的问题分解成不同的部分。例如,您有步骤1、2、3、4。步骤1、2、4有效,因为您已经调试了该过程,所以步骤3是问题所在。然后创建一个简单的项目,在其中以简化的方式重新创建问题(步骤3)。问题仍然存在吗?那么就在SO上发布它。问题不存在吗?这是您可以用来解决问题的线索。 - Fabrizio Bertoglio
调试建议使用这个宝石 https://github.com/deivid-rodriguez/pry-byebug - Fabrizio Bertoglio
显示剩余9条评论
1个回答

2

说实话,这是一个抽象的解决方案,与你的问题并没有直接关系,但它确实可行(基于生产代码的bootstrap+jq)

CoffeeScript

$.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 - 典型的Bootstrap模态框

<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 或其他 Rails 视图

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

打开模态框的链接

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

您可能希望使用自己的ajax请求 - 如果服务器出现错误/超时,这个请求不会做任何事情。

非常感谢您的回答!非常感激您的时间。会尝试实施您的解决方案。 - Anton S.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接