【问题标题】:Rails 5: handling error messages with rails-ujs and jqueryRails 5:使用 rails-ujs 和 jquery 处理错误消息
【发布时间】:2018-05-12 11:20:35
【问题描述】:

在 Rails 5.1.6 中,我尝试使用 rails-ujs 和 jquery 处理表单的错误消息。

lot.rb

class Lot < ActiveRecord::Base

    belongs_to :user

    mount_uploader :lot_image, LotImageUploader
    serialize :lot_images, JSON # If you use SQLite, add this line.
    default_scope -> { order('created_at DESC') }

    validates_processing_of :lot_image
    validate :image_size_validation
    validates :price, :lot_image, :description, presence: true

  private

    def image_size_validation
      errors[:lot_image] << "should be less than 5MB" if lot_image.size > 5.megabytes
    end
end

lots_controller.rb

...
  def index
    @lot = current_user.lots.build
    @lots = current_user.lots.paginate(page: params[:page])
  end
...
  def create
    @lot = current_user.lots.create(lot_params)

    respond_to do |format|
      if @lot.save
        format.html { redirect_to @lot, notice: 'Lot was successfully created.' }
        format.json { render :show, status: :created, location: @lot }
        format.js
      else
        #format.html { render action: "new" }
        format.json { render json: @lot.errors.full_messages, status: :unprocessable_entity }

      end
    end
  end
...

正如预期的那样,当我提交无效表单时,我在浏览器控制台中看到 422 状态和 json 响应:

0."Price can't be blank" 
1."Lot image can't be blank"
2."Description can't be blank"

问题是如何用rails-ujs渲染这个json响应?

_form.html.erb

<%= form_with(model: @lot, remote: true, id: :new_lot) do |form| %>
  <div id="errors"></div>

  <%= tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) %>

  <%= form.label :description, class: "label label-default" %>
  <%= form.text_area :description, class: "form-control", id: :lot_description, autofocus: true %>

  <%= form.label :price, class: "label label-default" %>
  <%= form.text_field :price, class: "form-control", id: :lot_price %>   

  <%= form.label :lot_image, class: "label label-default" %>
  <%= form.file_field :lot_image, id: :lot_lot_image %>
    <p class="help-block">image must be present, less than 5 Mb.</p>   

  <%= form.submit "create a lot", class: "btn btn-default", data: { "disable-with": "Saving..." } %>
<% end %>

create.js.erb

$('#new_lot').remove();
$('#new_lot_link').show();
$('#lots').prepend('<%= j render(@lot) %>')

application.js

//= require jquery
//= require rails-ujs
//= require turbolinks
//= require bootstrap-sprockets
//= require bootstrap
//= require_tree .


$(document).on("ajax:error", function(event) {
  var detail = event.detail;
  var data = detail[0], status = detail[1],  xhr = detail[2];

  var errors, message, results;
  errors = xhr.responseJSON.error;
  results = [];
  for (message in errors) {
    results.push($('#errors ul').append('<li>' + errors[message] + '</li>'));
  }
  return results;
});

出了什么问题?感谢您的任何解释,尤其是解决方案(;

【问题讨论】:

    标签: jquery ruby-on-rails-5.1 rails-ujs


    【解决方案1】:

    就像地球上最后一个人一样,我在自言自语(8

    我解决了这个问题。也许有人也会感兴趣。

    $(document).on("ajax:error", function(event) {
      var detail = event.detail;
      var data = detail[0], status = detail[1],  xhr = detail[2];
      var errors = JSON.parse(xhr.responseText);
      var er ="<ul>";
        for(var i = 0; i < errors.length; i++){
            var list = errors[i];
            er += "<li>"+list+"</li>"
       }
        er+="</ul>"
        $("#errors").html(er);
    });
    

    【讨论】:

    • 它只在ajax请求失败时调用,与服务器上的Rails功能无关
    【解决方案2】:

    这样怎么样?它不干净,因为在 js 文件中有一些控制器的工作,但它对我有用。我也找不到其他简单的方法。

    create.js.erb

    <% if !@lot.errors.any? %>
      $('#new_lot').remove();
      $('#new_lot_link').show();
      $('#lots').prepend('<%= j render(@lot) %>')
      <% @lot = Lot.new %>
    <% end %>
    $("#new_lot_form").html("<%= j (render 'form', lot: @lot) %>")
    

    确保在 _form.html.erb 部分显示错误。

    <% if lot.errors.any? %>
      <%= render 'shared/error_messages', object: form.object %>
    <% end %>
    

    当您使用创建操作中的@lot 变量重新加载表单时,它会显示错误消息。如果没有错误,它将追加新记录并需要创建新的@lot 变量 因为否则表单将获取已保存的对象,下次将发送您更新操作。

    将 format.js 添加到 lots_controller.erb

    中的 if @lot.save 的 else 部分
    ...
    respond_to do |format|
      if @lot.save
        format.html { redirect_to lots_path, notice: 'Lot was successfully created.' }
        format.json { render :show, status: :created, location: @lot }
        format.js
      else
        format.html { render :index }
        format.json { render json: @lot.errors, status: :unprocessable_entity }
        format.js
      end
    end
    ...
    

    index.erb 上使用 div#new_lot

    包装表单
    <div id="new_lot_form">
      <%= render 'form', lot: @lot %>
    </div>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-14
      相关资源
      最近更新 更多