我想通过highcharts在我的rails app中显示统计信息。当用户单击每个表行中可见的按钮时,将显示图表。单击按钮后,将使用数据库查询中使用的条目的id完成ajax发布。使用.done-回调,我试图遍历结果并将数据添加到图表中,但视图中的数组始终为空。查询的结果在控制器中正确显示,但在视图中始终为零。
查看:
$('.stats_btn').click(function() {
var info = $($(this).parent().siblings("#data_id")).get()
var data_id = parseInt(info[0].innerHTML);
$.ajax({
type: 'POST',
url: "/my_page/get_stats",
data: {id: data_id}
})
.done(function() {
$('#stats_modal').modal();
<%if @stats !=nil%>
chart = new Highcharts.Chart({
chart: {
renderTo: "stats_chart"
},
title: {
text: "Stats"
},
xAxis: {
type: "datetime"
},
yAxis: {
title: {
text: "Hits"
}
},
tooltip: {
formatter: function() {
return Highcharts.dateFormat("%B %e, %Y", this.x) + ': ' + Highcharts.numberFormat(this.y, 2) + " views";
}
},
series: [{
data: [
<%@stats.each do |video|%>
<%=video.hits%>,
<%end%>
]
}]
});
<%end%>
});
});
控制器:
@serdata_id = params[:id]
@stats = Serdata_serkeyword.group("date(serkeywords.date)").select("count(*) as hits").joins(:serdata).where("serdata.id = ?", @serdata_id).joins(:serkeyword).where("serkeywords.id = serkeyword_id")
@stats.each do |record|
logger.info record.hits
end
我知道ruby代码是在服务器端执行的,但是当我执行ajax post时,会创建一个新的控制器实例(?),因此必须初始化该数组。我是否误解了Rails中的工作原理,是否有更好的方法可以做到这一点?
答案 0 :(得分:1)
<强> JS 强>
首先,我会确保您的javascript是从document
对象委派的,因为这样可以确保您能够捕获事件,无论您是否使用Turbolinks
:< / p>
#app/assets/javascripts/application.js
$(document).on("click", ".stats_btn", function() {
// stuff here
})
虽然这不会对您的问题有所帮助,但它会帮助臭名昭着的JS赢得工作,因为Turbolinks只刷新<body>
标签,而不是{{1}标签&#34;问题
-
<强>控制器强>
关于你的控制器,如果服务器端查询被触发,则意味着你的ajax请求正在通过(这是个好消息)。解决问题的方法是确保您的<head>
处理程序可以收到响应
通常,您将使用respond_to
代码块处理响应:
ajax
-
<强> JSON 强>
我实际上建议您将ajax请求的#app/controllers/my_pages_controller.rb
Class MyPagesController < ApplicationController
def get_stats
respond_to do |format|
format.js #-> returns JS response
format.json #-> returns JSON response
end
end
end
属性更改为dataType
,因为这意味着您将能够接收纯JSON数据:
JSON
这意味着您可以执行以下操作:
$.ajax({
type: 'POST',
dataType: 'JSON',
url: "/my_page/get_stats",
-
查看强>
我认为您的主要问题是您设置#app/controllers/my_pages_controller.rb
Class MyPagesController < ApplicationController
respond_to :json, only: :get_stats
def get_stats
@serdata_id = params[:id]
@stats = Serdata_serkeyword.group("date(serkeywords.date)").select("count(*) as hits").joins(:serdata).where("serdata.id = ?", @serdata_id).joins(:serkeyword).where("serkeywords.id = serkeyword_id")
respond_with @stats #-> automatically encodes JSON
end
end
回调的方式 -
$.ajax
首先,您的$.ajax({
type: 'POST',
url: "/my_page/get_stats",
data: {id: data_id}
})
.done(function() {
$('#stats_modal').modal();
<%if @stats !=nil%>
chart = new Highcharts.Chart({
chart: {
renderTo: "stats_chart"
},
title: {
text: "Stats"
},
xAxis: {
type: "datetime"
},
yAxis: {
title: {
text: "Hits"
}
},
tooltip: {
formatter: function() {
return Highcharts.dateFormat("%B %e, %Y", this.x) + ': ' + Highcharts.numberFormat(this.y, 2) + " views";
}
},
series: [{
data: [
<%@stats.each do |video|%>
<%=video.hits%>,
<%end%>
]
}]
});
<%end%>
});
与任何事件/元素都没有关联,这意味着它不会运行。其次,.done
方法(或用于捕获done
响应的方法只有在您将返回的ajax
传递给它时才有效
我建议使用以下内容:
data
此外,您无法在标准JS中使用$.ajax({
type: 'POST',
url: "/my_page/get_stats",
data: {id: data_id}
success: function(data) {
// returned data here
}
});
- 您只能在后端代码中使用@instance variables
。在您的情况下,您应该将JSON请求传递给您的控制器&amp;然后使用@instance variables
函数中的data
参数来处理返回的JSON对象
这将确保您能够处理前端所需的数据
如果您希望我对所提供的代码更加具体,请告知我们&amp;我会更新你的信息!
-
<强>更新强>
您不能在前端JS / Ajax中使用success
的原因只是前端。 Ajax(Asynchronous Javascript And XML)用于发送HTTP请求&#34;在幕后&#34; - 意味着您的Ajax请求就像&#34;伪&#34;浏览器(IE唯一的前端)
您遇到的问题是如果在后端(您的控制器)中设置@instance variables
- 因为您的Ajax只是前端,这意味着它无法从控制器访问@instance variables
。这意味着您的ajax只能读取您从控制器后端发送的数据
如果您在views文件夹中创建了@instance variables
,那么您就可以使用所需的js.erb