Rails没有显示Ajax调用后,提示信息提示信息、Rails、Ajax

2023-09-10 16:12:22 作者:一骑当十千

我在写一个Rails 4.0.2应用程序,并想获得一个Flash的通知AJAX事件后,在我看来,以显示。

在我看来,我显示与天日历,用户可以点击。当他们这样做,我通过一个onclick事件处理程序,该更新我的模型,要么添加或删除一条记录触发一个AJAX事件。触发事件之后,我为了显示更新的结果完成刷新页面。

我发现我有JS的单击事件期间做了页面刷新,以获取视图正确更新。一个重定向或使控制器单单是不够的。

所以,这种效果,我在控制器中设置一个闪光的通知...

 高清set_conflicts
  @conflict = @ member.conflicts.for_date(PARAMS [:日期])第一。

  如果@conflict
    @ conflict.destroy
  其他
    conflict_date = Date.parse(PARAMS [:日期])
    除非Conflict.create(
        月:conflict_date.month,
        天:conflict_date.day,
        年:conflict_date.year,
        成员:@member
    )
      闪光[:警惕] ='糟糕,问题更新冲突
    结束
  结束
  闪光[:通知] ='这是一个测试!
  redirect_to时ma​​nage_member_conflicts_path(@member)
结束
 

...并已包括以下Flash显示的逻辑我的 application.haml

  ...
%体
  = P flash.inspect
   -  flash.each做|类型,信息|
    = content_tag(:DIV,消息,:类=>中闪光 - #{类型})

  =渲染设计/菜单/ login_items
  =产量
 
vue中选择弹出提示框 可选择yes 或no DELMIA软件 文本信息提示框功能介绍与使用方法...

注:我用HAML代替ERB在我的意见的

然而,不管我怎么努力,闪光灯消息不显示。其他一切工作正常的除了的在的即显信息的,然后我一直无法弄清楚的为什么的。

我怀疑它有东西做与AJAX刷新我做结合重定向(甚至turbolinks),但我已经通过其他的答案在这里看着SO根本无法得到它的工作。很显然,我失去了一些东西。

这里的JS click处理程序(它的pretty的简单):

  window.calendarClick =(EVENTDATE,linkURL) - >
  事件= $(的document.getElementById(EVENTDATE))
  event.toggleClass('选择')

  #设置或删除冲突
  $就
    网址:linkURL
    数据:
      日期:EVENTDATE

  #刷新页面
  $就
    网址:'',
    背景:document.body的,
    成功:(S,X) - >
      $(本)。html的(S)
 

解决方案

首先,感谢COM prehensive问题

下面是一个同样COM prehensive答案:How你怎样对待铁路的闪光灯Ajax请求?

阿贾克斯

我会认真看你的阿贾克斯刷新过程。刷新整个页面是超级低效的,而且我认为覆盖更深层次的问题

你为什么不尝试在使用 .js.erb 文件视图文件夹,处理JS直接由该方法

 高清set_conflicts
  @conflict = @ member.conflicts.for_date(PARAMS [:日期])第一。

  如果@conflict
    @ conflict.destroy
  其他
    conflict_date = Date.parse(PARAMS [:日期])
    除非Conflict.create(
        月:conflict_date.month,
        天:conflict_date.day,
        年:conflict_date.year,
        成员:@member
    )
      闪光[:警惕] ='糟糕,问题更新冲突
    结束
  结束
  闪光[:通知] ='这是一个测试!

  respond_to代码做|格式|
      的format.html {redirect_to时ma​​nage_member_conflicts_path(@member)}
      format.js
  结束
结束

#应用程序/视图/控制器/ set_conflicts.js.erb
$(#your_element)HTML(<%= j的渲染manage_member_conflicts_path(@member))%>);
 

响应

虽然我不知道这是肯定的,我知道的Flash对象是由 ActionDispatch处理::闪存中间件。我相信XHR以同样的方式为标准的HTTP请求,因此preventing被显示在你的回应的Flash,这是没有处理

这意味着你必须做一些事情,通过你的Ajax请求传递Flash对象。而据我张贴在这个答案顶部的问题,你可以使用响应头来做到这一点:

 类的ApplicationController< ActionController的::基地
after_filter:flash_to_headers

高清flash_to_headers
  返回除非request.xhr?
  response.headers ['X-信息'] =闪光[:错误除非闪光灯[:错误] .blank?
  #重复其他闪存类型...

  flash.discard#不想闪光灯,当你重新加载页面出现
结束

$(文件).ajaxError(函数(事件,要求){
  VAR味精= request.getResponseHeader(X-信息');
  如果(MSG)警报(味精);
});
 

I'm writing a rails 4.0.2 app, and am trying to get a Flash notice to display in my view after an AJAX event.

In my view I display a calendar with days a user can click on. When they do so, I fire an AJAX event via an onclick event handler which updates my model, either adding or removing a record. After firing the event, I complete a page refresh in order to display the updated results.

I found I had to do a page refresh during the JS click event in order to get the view to update properly. A redirect or render in the controller alone wasn't enough.

So, to that effect, I have set a Flash notice in my controller...

def set_conflicts
  @conflict = @member.conflicts.for_date(params[:date]).first

  if @conflict
    @conflict.destroy
  else
    conflict_date = Date.parse(params[:date])
    unless Conflict.create(
        month: conflict_date.month,
        day:   conflict_date.day,
        year:  conflict_date.year,
        member: @member
    )
      flash[:alert] = 'Oops, there was a problem updating conflicts'
    end
  end
  flash[:notice] = 'This is a test!'
  redirect_to manage_member_conflicts_path(@member)
end

... and have included the following flash display logic in my application.haml...

...
%body
  = p flash.inspect
  - flash.each do |type, message|
    = content_tag(:div, message, :class => "flash-#{type}")

  = render 'devise/menu/login_items'
  = yield

Note: I use HAML instead of ERB in my views

Yet, no matter what I try, the Flash message does not display. Everything else works as expected except the flash message, and I haven't been able to figure out why.

I suspect it's got something to do with the AJAX refresh I'm doing combined with the redirect (and maybe even turbolinks) but I've looked through other answers here on SO and simply can't get it to work. Clearly, I'm missing something.

Here's the JS click handler (it's pretty simple):

window.calendarClick = (eventDate, linkURL) ->
  event = $(document.getElementById(eventDate))
  event.toggleClass('selected')

  # Set or Remove conflicts
  $.ajax
    url: linkURL
    data:
      date: eventDate

  # Refresh the page
  $.ajax
    url: '',
    context: document.body,
    success: (s,x) ->
      $(this).html(s)

解决方案

Firstly, thanks for comprehensive question

Here is an equally comprehensive answer: How do you handle Rail's flash with Ajax requests?

Ajax

I'd seriously look at your Ajax refresh process. Refreshing the whole page is super inefficient, and I think covering a deeper issue

Why don't you try using a .js.erb file in the views folder, to handle JS directly by the method:

def set_conflicts
  @conflict = @member.conflicts.for_date(params[:date]).first

  if @conflict
    @conflict.destroy
  else
    conflict_date = Date.parse(params[:date])
    unless Conflict.create(
        month: conflict_date.month,
        day:   conflict_date.day,
        year:  conflict_date.year,
        member: @member
    )
      flash[:alert] = 'Oops, there was a problem updating conflicts'
    end
  end
  flash[:notice] = 'This is a test!'

  respond_to do |format|
      format.html { redirect_to manage_member_conflicts_path(@member) }
      format.js 
  end
end

#app/views/controller/set_conflicts.js.erb
$("#your_element").html(<%=j render manage_member_conflicts_path(@member) ) %>);

Response

Although I don't know this for sure, I know the Flash objects are handled by ActionDispatch::Flash middleware. I believe this is not handled for XHR in the same way as standard HTTP requests, consequently preventing Flash from being shown in your response

This means you'll have to do something to pass the Flash object through your Ajax request. And according to the question I posted at the top of this answer, you can use the response headers to do it:

class ApplicationController < ActionController::Base
after_filter :flash_to_headers

def flash_to_headers
  return unless request.xhr?
  response.headers['X-Message'] = flash[:error]  unless flash[:error].blank?
  # repeat for other flash types...

  flash.discard  # don't want the flash to appear when you reload page
end

$(document).ajaxError(function(event, request) {
  var msg = request.getResponseHeader('X-Message');
  if (msg) alert(msg);
});