【问题标题】:Rails Modal Form - Can't Get Validation Errors to Display in ModalRails 模态表单 - 无法在模态中显示验证错误
【发布时间】:2013-03-18 05:09:51
【问题描述】:

编辑:我忘了提到我在模型级别使用验证,而且效果很好。因此,验证阻止了模式表单的提交(并且 ajax:error 被调用),但我没有运气处理生成的错误对象并正确显示错误。现在我只使用占位符文本(“FORM HAS ERRORS”)。同样,验证和显示错误在我的非模态(非 ajax)表单(我使用部分错误消息)中工作正常。我真的希望我可以在我的模态对话框中渲染那个部分,你会认为这很简单。

我正在为此拉头发。

我有一个“添加游览”表单,在该表单中,您可以从数据库中选择建筑物以添加到游览中(我正在使用 jquery tokeninput 来搜索和选择建筑物)。一切都很好。

我通过提供“添加建筑物”链接为用户添加了添加新建筑物的功能,该链接会显示一个模式表单。我处理了结果,一切正常(建筑被保存,模式被解除,令牌被添加等等)。

除了模态表单中的验证之外,一切都很好。 . .这根本不起作用。我试过client_side_validations,我试过写咖啡脚本来遍历控制器返回的错误对象等等。

无论如何,我已经尝试了我所知道的一切尝试,所以现在我要向你们寻求帮助。现在我只是在咖啡脚本文件中有占位符错误处理代码(它只是以非常基本的方式显示“FORM HAS ERRORS”)。我放弃了之前的所有尝试来制作这项工作,因为它越来越难看,我真的只是在寻找最好的方法来做到这一点。

这里是相关文件。

building.js.coffee

$ ()->
  $("form.new_building").on "ajax:success", (event, data, status, xhr) ->
    $("form.new_building")[0].reset()
    $('#new-building-modal').modal('hide')
    fulladdress = "#{data.address} (#{data.name}, #{data.city}, #{data.zip})"
    $('#tour_building_tokens').tokenInput("add", {id: data.id, address: fulladdress} )

  $("form.new_building").on "ajax:error", (event, xhr, status, error) ->
    $('#display_errors').append('<font color="red"><strong>FORM HAS ERRORS</strong></font><br><br>')
    $('#display_errors').show()

buildings_controller.rb

....

def create
    @building = Building.new(params[:building])

    respond_to do |format|
      if @building.save
        format.html { redirect_to @building, notice: 'Building Created!' }
        format.json { render json: @building, status: :created, location: @building }
      else
        format.html { render 'new' }
        format.json { render json: @building.errors, status: :unprocessable_entity }
      end
    end
end

new.html.erb

<% provide(:title, 'Add Tour') %>

<h1>Add Tour</h1>

<div class="row">
    <div class="span6 offset3">
        <%= form_for(@tour) do |f| %>

            <%= render 'fields', f: f %>

            <%= link_to 'Add Building', '#new-building-modal', 'data-toggle' => "modal" %>

            </br>
            </br>

            <%= f.submit "Add Tour", class: "btn btn-large btn-primary" %>
        <% end %>
    </div>
</div>


<div id='new-building-modal' class='modal hide fade'>


            <div class = "modal-body">

                <%= form_for(Building.new, remote:true, html: {"data-type" => :json}) do |f| %>

                    <div id="display_errors" style="display:none;">
                    </div>

                    <%= f.label :name %>
                    <%= f.text_field :name %>

                    <%= f.label :address %>
                    <%= f.text_field :address %>

                    <%= f.label :city %>
                    <%= f.text_field :city %>

                    <%= f.label :zip %>
                    <%= f.text_field :zip %>

            </div>

            <div class = "modal-footer">

                    <%= f.submit "Add Building", class: "btn btn-large btn-primary" %>
            </div>

                <% end %>
</div>

哦,我还有一个共享的错误消息部分,我现在没有在此模式中使用(因为我无法让模式“刷新”以显示错误)。在一个完美的世界中,我会在模态中使用相同的部分,因为它与我的其他非模态形式很好。

这里是部分(同样,目前在上面的代码中没有渲染它)。

<% if object.errors.any? %>
<div id="error_explanation">
    <div class="alert alert-error">
        The form contains <%= pluralize(object.errors.count, "error") %>.
    </div>
    <ul>
        <% object.errors.full_messages.each do |msg| %>
            <% if msg != "Password digest can't be blank" %>
                <li>* <%= msg %></li>
            <% end %>
        <% end %>
    </ul>
</div>

提前感谢任何人提供的任何帮助。我需要尽可能多的细节。我在 Stack Overflow 上研究过相关问题,每次我认为我很接近时,我都会空手而归。

【问题讨论】:

    标签: ruby-on-rails validation modal-dialog


    【解决方案1】:

    感谢muttonlamb 为我指明了正确的方向。我有 50% 的把握肯定它必须通过解析 JSON 来做点什么,他说服我继续走这条路。具有讽刺意味的是,是 this SO question 帮助我得到了最终答案。这个问题的答案,包括将错误打印到控制台,正是我想要的。事实证明,我解析错误并没有太多。 . .我正在解析错误的对象。这是最终的有效实现。 . .

    新的coffeescript(请注意我如何根据需要显示、隐藏和清除 div):

    $ ()->
      $("form.new_building").on "ajax:success", (event, data, status, xhr) ->
        $("form.new_building")[0].reset()
        $('#new-building-modal').modal('hide')
        fulladdress = "#{data.address} (#{data.name}, #{data.city}, #{data.zip})"
        $('#tour_building_tokens').tokenInput("add", {id: data.id, address: fulladdress} )
        $('#error_explanation').hide()
    
      $("form.new_building").on "ajax:error", (event, xhr, status, error) ->
        errors = jQuery.parseJSON(xhr.responseText)
        errorcount = errors.length
        $('#error_explanation').empty()
        if errorcount > 1
          $('#error_explanation').append('<div class="alert alert-error">The form contains ' + errorcount + ' errors.</div>')
        else
          $('#error_explanation').append('<div class="alert alert-error">The form contains 1 error</div>')
        $('#error_explanation').append('<ul>')
        for e in errors
          $('#error_explanation').append('<li>' + e + '</li>')
        $('#error_explanation').append('</ul>')
        $('#error_explanation').show()
    

    新视图:

    <% provide(:title, 'Add Tour') %>
    
    <h1>Add Tour</h1>
    
    <div class="row">
        <div class="span6 offset3">
            <%= form_for(@tour) do |f| %>
    
                <%= render 'fields', f: f %>
    
                <%= link_to 'New Building', '#new-building-modal', 'data-toggle' => "modal" %>
    
                </br>
                </br>
    
                <%= f.submit "Add Tour", class: "btn btn-large btn-primary" %>
            <% end %>
        </div>
    </div>
    
    
    <div id='new-building-modal' class='modal hide fade'>
    
                <div class = "modal-header">
                    <div id="error_explanation" style="display:none;">
                    </div>
                </div>
    
                <div class = "modal-body">
    
                    <%= form_for(Building.new, remote:true, html: {"data-type" => :json}) do |f| %>
    
                        <%= f.label :name %>
                        <%= f.text_field :name %>
    
                        <%= f.label :address %>
                        <%= f.text_field :address %>
    
                        <%= f.label :city %>
                        <%= f.text_field :city %>
    
                        <%= f.label :zip %>
                        <%= f.text_field :zip %>
    
                </div>
    
                <div class = "modal-footer">
    
                        <%= f.submit "Add Building", class: "btn btn-large btn-primary" %>
                </div>
    
                    <% end %>
    </div>
    

    新控制器:

    def create
         @building = Building.new(params[:building])
    
        respond_to do |format|
          if @building.save
            format.html { redirect_to @building, notice: 'Building Created!' }
            format.json { render json: @building, status: :created, location: @building }
          else
            format.html { render 'new' }
            format.json { render json: @building.errors.full_messages, status: :unprocessable_entity }
            end
        end
      end
    

    最后,为了在添加错误时防止模式滚动(我希望它自动调整大小),我添加了这个 CSS:

    #new-building-modal {
        max-height: 600px;
    }
    

    希望所有这些细节能够避免其他人不得不在愚蠢的模态验证错误上浪费近一周的时间。

    【讨论】:

      【解决方案2】:

      您的 ajax 请求错误部分似乎没有运行。

      原因是这样,您要查找的错误可能是“找不到页面”或其他一些 HTTP 错误。

      在您的控制器中,HTTP 请求仍然会成功,即它仍然会返回数据。

      处理是否存在错误的逻辑应该在 ajax 成功块中。

      希望这是有道理的

      $ ()->
        $("form.new_building").on "ajax:success", (event, data, status, xhr) ->
          $("form.new_building")[0].reset()
          $('#new-building-modal').modal('hide')
          fulladdress = "#{data.address} (#{data.name}, #{data.city}, #{data.zip})"
          $('#tour_building_tokens').tokenInput("add", {id: data.id, address: fulladdress} )
      

      您需要检查本节中的错误变量。

      【讨论】:

      • 我一开始也是这么想的,但我添加了“FORM HAS ERRORS”通用错误消息,当验证触发错误时它会被调用。因此,正在调用 ajax 错误部分。但是,我无法处理控制器返回的错误对象(我猜它会包含 JSON?)。
      • api.jquery.com/jQuery.getJSON 有一些关于根据返回的 JSON 实际更新视图的好信息。
      猜你喜欢
      • 2015-12-14
      • 2017-06-12
      • 2016-01-30
      • 2014-01-05
      • 1970-01-01
      • 1970-01-01
      • 2022-11-12
      • 2014-01-17
      • 2020-01-20
      相关资源
      最近更新 更多