Rails - Simple Form Bootstrap - 显示完整的错误文本内联 - (或任何位置)

3

我在尝试使用Rails 5中的简单表单,以便在我的表单中显示完整的错误信息,但我无法理解如何实现。我只能看到一个顶部带有消息的框:

Please review the problems below:  

我没有看到问题列表或任何突出显示的表单字段。

我按照这篇文章中的建议,在我的初始化程序中将所有对错误的引用替换为“full_error”,但这仅解决了父表单的问题-嵌套字段仍然只会得到不完整的错误消息。有人知道如何在simple form中识别错误吗?

# Use this setup block to configure all options available in SimpleForm.
SimpleForm.setup do |config|
  config.error_notification_class = 'alert alert-danger'
  config.button_class = 'btn btn-green'
  config.boolean_label_class = nil

  config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
    b.use :html5
    b.use :placeholder
    b.optional :maxlength
    b.optional :pattern
    b.optional :min_max
    b.optional :readonly
    b.use :label, class: 'control-label'

    b.use :input, class: 'form-control'
    b.use :full_error, wrap_with: { tag: 'span', class: 'help-block' }
    b.use :hint,  wrap_with: { tag: 'p', class: 'help-block' }
  end

  config.wrappers :vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
    b.use :html5
    b.use :placeholder
    b.optional :maxlength
    b.optional :readonly
    b.use :label, class: 'control-label'

    b.use :input
    b.use :full_error, wrap_with: { tag: 'span', class: 'help-block' }
    b.use :hint,  wrap_with: { tag: 'p', class: 'help-block' }
  end

  config.wrappers :vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
    b.use :html5
    b.optional :readonly

    b.wrapper tag: 'div', class: 'checkbox' do |ba|
      ba.use :label_input
    end

    b.use :full_error, wrap_with: { tag: 'span', class: 'help-block' }
    b.use :hint,  wrap_with: { tag: 'p', class: 'help-block' }
  end

  config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
    b.use :html5
    b.optional :readonly
    b.use :label, class: 'control-label'
    b.use :input
    b.use :full_error, wrap_with: { tag: 'span', class: 'help-block' }
    b.use :hint,  wrap_with: { tag: 'p', class: 'help-block' }
  end

  config.wrappers :horizontal_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
    b.use :html5
    b.use :placeholder
    b.optional :maxlength
    b.optional :pattern
    b.optional :min_max
    b.optional :readonly
    b.use :label, class: 'col-sm-3 control-label'

    b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
      ba.use :input, class: 'form-control'
      ba.use :full_error, wrap_with: { tag: 'span', class: 'help-block' }
      ba.use :hint,  wrap_with: { tag: 'p', class: 'help-block' }
    end
  end

  config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
    b.use :html5
    b.use :placeholder
    b.optional :maxlength
    b.optional :readonly
    b.use :label, class: 'col-sm-3 control-label'

    b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
      ba.use :input
      ba.use :full_error, wrap_with: { tag: 'span', class: 'help-block' }
      ba.use :hint,  wrap_with: { tag: 'p', class: 'help-block' }
    end
  end

  config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
    b.use :html5
    b.optional :readonly

    b.wrapper tag: 'div', class: 'col-sm-offset-3 col-sm-9' do |wr|
      wr.wrapper tag: 'div', class: 'checkbox' do |ba|
        ba.use :label_input
      end

      wr.use :full_error, wrap_with: { tag: 'span', class: 'help-block' }
      wr.use :hint,  wrap_with: { tag: 'p', class: 'help-block' }
    end
  end

  config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
    b.use :html5
    b.optional :readonly

    b.use :label, class: 'col-sm-3 control-label'

    b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
      ba.use :input
      ba.use :full_error, wrap_with: { tag: 'span', class: 'help-block' }
      ba.use :hint,  wrap_with: { tag: 'p', class: 'help-block' }
    end
  end

  config.wrappers :inline_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
    b.use :html5
    b.use :placeholder
    b.optional :maxlength
    b.optional :pattern
    b.optional :min_max
    b.optional :readonly
    b.use :label, class: 'sr-only'

    b.use :input, class: 'form-control'
    b.use :full_error, wrap_with: { tag: 'span', class: 'help-block' }
    b.use :hint,  wrap_with: { tag: 'p', class: 'help-block' }
  end

  config.wrappers :multi_select, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
    b.use :html5
    b.optional :readonly
    b.use :label, class: 'control-label'
    b.wrapper tag: 'div', class: 'form-inline' do |ba|
      ba.use :input, class: 'form-control'
      ba.use :full_error, wrap_with: { tag: 'span', class: 'help-block' }
      ba.use :hint,  wrap_with: { tag: 'p', class: 'help-block' }
    end
  end
  # Wrappers for forms and inputs using the Bootstrap toolkit.
  # Check the Bootstrap docs (http://getbootstrap.com)
  # to learn about the different styles for forms and inputs,
  # buttons and other elements.
  config.default_wrapper = :vertical_form
  config.wrapper_mappings = {
    check_boxes: :vertical_radio_and_checkboxes,
    radio_buttons: :vertical_radio_and_checkboxes,
    file: :vertical_file_input,
    boolean: :vertical_boolean,
    datetime: :multi_select,
    date: :multi_select,
    time: :multi_select
  }
end

表单

<%= simple_form_for(@proposal) do |f| %>
  <%= f.error_notification %>

 <% @proposal.errors.full_messages.each do |msg| %>
    <%= li= msg %>
 <% end %>



  <div class="form-inputs" style="margin-bottom: 50px">
  <!--   General Organisation details -->
    <div class="row">
      <div class="col-md-12">
        <%= f.input :title, :label => "Title" %>

      </div>
    </div>
    <div class="row">
      <div class="col-md-12">
        <%= f.input :byline, :label => "Tagline" %>
      </div>
    </div>

    <div class="row">
      <div class="col-md-12">
        <%= f.input :description, as: :text, :label => "Outline your proposal", input_html: { rows: 15 } %>
      </div>
    </div>




  <!--   Package: :ethics considerations -->
  <div class="row">
    <div class="col-md-12">
      <div class="form_title">Research Ethics</div>
    </div>
  </div>

  <div class="row">
    <div class="col-md-12">

    <%= f.simple_fields_for :ethics do |f| %>
      <%= f.error_notification %>
        <%= render 'package/ethics/ethics_fields', f: f %>

    <% end %>

    <%= link_to_add_association 'Add another ethics issue', f, :ethics, partial: 'package/ethics/ethics_fields' %>
    </div>
  </div>


  </div>

  <div class="row">
    <div class="col-md-10 col-md-offset-1" style="margin-top: 50px">
      <div class="form-actions">
        <%= f.button :submit %>
      </div>
    </div>
  </div>
<% end %>

嵌套字段

<div class="nested-fields">

    <%# @proposal.ethics.errors.full_messages.each do |e| %>
        <li><%#=  e  %></li>
    <%# end %>
    <div class="form-inputs">
      <div class="row">
          <div class="col-md-12 ">
          <%= f.select :category, [ "Risk of harm", "Informed consent", "Anonymity and Confidentiality", "Deceptive practices", "Right to withdraw"], { label: "Principle" }, id: "main_category" %>
          <%= f.select :subcategory, [], {}, id: "sub_category", disabled: true %>
          <%= f.input :consideration, as: :text, :label => "Identify the ethics considerations?",  :input_html => {:rows => 8} %>
          <%= f.input :plan, as: :text, :label => "How will these considerations be managed?",  :input_html => {:rows => 8} %>
        </div>
      </div>
  </div>
  <div class="row">
      <div class="col-md-6" style="margin-top: 20px; margin-bottom: 50px">
        <%= link_to_remove_association 'Remove this ethical issue', f %>
      </div>

  </div>
</div>

请粘贴您的表单。 - Sravan
4个回答

1

看起来你在错误显示代码中混淆了haml和erb。

这个:

 <% @proposal.errors.full_messages.each do |msg| %>
   <%= li= msg %>
 <% end %>

应该更像这样:

应该更像这样:

<% if @proposal.errors.any? %>
<ul>
  <% @proposal.errors.full_messages.each do |msg| %>
    <li><%= msg %></li>
  <% end %>
</ul>
<% end %>

我猜测你正在使用Cocoon,因此需要正确设置,但在使用Rails 5时有一个注意点。
您的模型需要类似以下内容:
class Proposal < ApplicationRecord
  has_many: :ethics, inverse_of: :proposal
  accepts_nested_attributes_for :ethics ...
...

并且

class Ethic < ApplicationRecord
  belongs_to :proposal, inverse_of: :ethics
...

请注意 has_many .. inverse_of 子句,它可以解决 Rails 5 中的一个错误。
如果正确设置 accepts_nested_attributes_for 子句,我认为 @proposal.errors 应该包含表单中的所有错误。

在道德模型的反向问题上您是正确的 - 这使错误消失了,但是我如何打印道德表单嵌套部分中伦理属性的错误呢?它们在表单顶部与提案错误列表一起列出,但当我滚动到伦理属性时,只会得到一个红色框,上面写着“请查看下面的问题”,然后没有列表。 - Mel
我认为没有明显的方法可以分离父错误和子错误。我会从simple_fields_for块中删除"<%= f.error_notification %>"行,并依赖simple_form来生成您的错误消息。顺便说一句,正如Sravan所说,您需要为simple_fields_for块使用不同的变量。 - Ben Trewern
但它实际上与 f :f 很好地运作 - 我不确定我是否需要它。属性使用 f (与建议相同) 创建。 - Mel
请注意:simple_fields_for块内的f是不同的(本地)变量,与simple_form_for块内的f不同。更改它的名称可以使其明显,并且如果您(或其他人)需要重新访问此表单,则可能有所帮助。 - Ben Trewern

0

0

我在你的代码中发现的第一个错误是,在嵌套字段中,你在参数中使用了相同的变量f,这可能会与父级参数f混淆。

因此,嵌套将是:

<%= f.simple_fields_for :ethics do |ff| %>
      <%= ff.error_notification %>
      <%= render 'package/ethics/ethics_fields', f: f %>
<% end %>

现在是表单:

<%= simple_form_for(@proposal) do |f| %>
  <%= f.error_notification %>

 <% @proposal.errors.full_messages.each do |msg| %>
    <%= li= msg %>
 <% end %>



  <div class="form-inputs" style="margin-bottom: 50px">
  <!--   General Organisation details -->
    <div class="row">
      <div class="col-md-12">
        <%= f.input :title, :label => "Title" %>

      </div>
    </div>
    <div class="row">
      <div class="col-md-12">
        <%= f.input :byline, :label => "Tagline" %>
      </div>
    </div>

    <div class="row">
      <div class="col-md-12">
        <%= f.input :description, as: :text, :label => "Outline your proposal", input_html: { rows: 15 } %>
      </div>
    </div>




  <!--   Package: :ethics considerations -->
  <div class="row">
    <div class="col-md-12">
      <div class="form_title">Research Ethics</div>
    </div>
  </div>

  <div class="row">
    <div class="col-md-12">

    <%= f.simple_fields_for :ethics do |ff| %>
      <%= ff.error_notification %>
        <%= render 'package/ethics/ethics_fields', f: ff %>

    <% end %>

    <%= link_to_add_association 'Add another ethics issue', f, :ethics, partial: 'package/ethics/ethics_fields' %>
    </div>
  </div>


  </div>

  <div class="row">
    <div class="col-md-10 col-md-offset-1" style="margin-top: 50px">
      <div class="form-actions">
        <%= f.button :submit %>
      </div>
    </div>
  </div>
<% end %>




<%= f.simple_fields_for :ethics do |ff| %>
    <%= ff.error_notification %>
    <%= render 'package/ethics/ethics_fields', f: ff %>
    <% @proposal.ethics.errors.full_messages.each do |msg| %>
        <%= li= msg %>
    <% end %>
<% end %>

编辑:即使上述方法不能解决问题,

尝试从@proposal变量的ethics对象获取错误信息。

因此,

<%= f.simple_fields_for :ethics do |ff| %>
    <%= ff.error_notification %>
    <% @proposal.ethics.errors.full_messages.each do |msg| %>
    <%= li= msg %>
    <% end %>
    <%= render 'package/ethics/ethics_fields', f: f %>
<% end %>

请检查这个回答,如有任何疑问请随时询问。 - Sravan
但如果是这样的话,所有伦理学领域都不会起作用。在伦理嵌套字段部分中,f.input对于输入元素可以正常工作。我找不到一种方法来显示该表单中的错误。 - Mel
伦理领域可能会起作用,但错误消息可能无法显示。请检查答案的最后部分。 - Sravan
在视图中只需打印出 @proposal.errors,并检查其中是否有伦理对象。 - Sravan
它确实可以。但我无法使错误以表格形式打印出来。 - Mel
让我们试一试,你在 @proposal.errors 中得到了什么? - Sravan

0

另一个选择可能是直接在字段上显示错误消息。

<%= f.input :title, :label => "Title", id:"title" %>
<%= f.error :title, :id => "title_error" %>

这将在标题字段旁显示标题的错误消息。您可以为表单中的每个字段添加f.error方法,而不是在表单上方显示<ul>,或者与表单上方的<ul>一起显示。

对于嵌套表单字段,请尝试将validates_associated :assoc_model_name添加到主模型中。这将运行关联模型的验证。


这应该是通过使用simple_form gem自动发生的。它在需要时包括相关字段的错误信息。 - Ben Trewern

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