我正在尝试在选择州和城市时显示图表。
城市下拉列表根据第一个下拉列表中的州选择进行填充。
问题是当我点击一个城市时没有显示图表,如果我更改了选择也没有更新,我似乎无法弄清楚问题。
我正在使用ChartKick显示一个饼图,其中包含控制器中查询给出的值。
我的代码如下:
控制器/ city_stats_controller.rb:
def city_stats
@state = params[:state]
@cities = City.where(:state => @state).select(:id, :display_name).uniq.order('display_name ASC')
# @city_id = City.select('id').where(:state => params[:city_state]).where(:name => params[:city_name])
@city_id = City.select('id').find_by_id(params[:city])
dynamic_query = ActiveRecord::Base.send(:sanitize_sql_array, ['SELECT COALESCE(name) as name, count(*) FROM (SELECT name, regs.segment_id, count(*) FROM regs
INNER JOIN segments ON regs.segment_id = segments.id
WHERE regs.city_id = ?
GROUP BY segment_id, name
ORDER BY count(*) DESC) as tabe
GROUP BY name;', @city_id])
@spatial_ratio = ActiveRecord::Base.connection.select_all(dynamic_query)
puts @city_id.inspect #I can see the value printed in the terminal
puts @spatial_ratio.inspect #Same here, even after changing the selection
respond_to do |format|
format.json { render :json => @cities }
format.js {
render json: {
html: render_to_string(
partial: 'city_stats',
locals: {
city_id: @city_id,
spatial_ratio: @spatial_ratio
})
}
}
format.html
end
end
views / city_stats / city_stats.html.erb:
<div class="row">
<label>State <span>:</span></label>
<%= collection_select :city, :state, City.select(:state).uniq.order('state ASC'), :state, :state, {:prompt => 'Select a State'}, {id: 'city_state', multiple: false} %>
<label>City <span>:</span></label>
<%= collection_select :city, :name, [], :name, :name, {:prompt => 'Select a City'}, {id: 'city_name', multiple: false} %>
</div>
<div id="cities">
<!-- Here I render the cities list upon selecting a state-->
<%= render :partial => 'city_stats', :object => @cities %>
</div>
<div id="stats">
</div>
<script type="text/javascript">
$(document).ready(function() {
$("#city_state").on('change', function(){
$.ajax({
url: "/admin/city_stats",
type: "GET",
data: {state: $(this).val()},
success: function(data) {
$("#city_name").children().remove();
// Create options and append to the list
var listitems = [];
$.each(data,function(key, value) {
listitems += '<option value="' + value.id + '">' + value.display_name + '</option>';
});
$("#city_name").append(listitems);
//console.log(listitems);
$("#city_name").on('click', function(){
$.ajax({
url: "/admin/city_stats",
type: "GET",
data: {city: $(this).val()},
success: function(data) {
var content = $("#city_name").val()
console.log(content);
$('#stats').replaceWith("<%= j render(partial: 'city_stats') %>");
return content;
}
})
})
}
})
});
});
在partial:views / city_stats / _city_stats.html.erb中:
<%= pie_chart @spatial_ratio.rows %>
注意:如果我手动用随机ID替换控制器中动态查询中的city_id,则刷新页面时会显示相应城市的图表,但我不知道为什么它不能动态地工作
答案 0 :(得分:1)
@city_id = City.select('id').find_by_id(params[:city])
此行不会返回一个数字。它返回一个模型实例,只加载了一个字段(id)。尝试将其更改为
@city_id = City.select('id').find_by_id(params[:city]).id
那会给你一个号码。
另外,正如我所见,在$("#city_name").on('click')
的AJAX处理程序中,您实际上并未使用生成的图表更新视图。
<%= j render(partial: 'city_stats') %>
此行仅在html页面的初始呈现时进行一次评估(这就是为什么在手动设置city_id
时一切正常),因此在每个AJAX请求中,不会重新加载完全是您的网页,您将$('#stats')
替换为相同的内容。
顺便说一下,一旦你替换$('#stats')
,你就不会在没有完全重新呈现页面的情况下下次访问它,因为它会从DOM中删除。参见(replaceWith)的参考文献。
我认为,对于AJAX,最好在$('#stats')
容器上使用.empty(),然后在其中使用.append()新图表。
我们的想法是,如果您想在不重新加载页面的情况下更新图表,则应使用服务器中的新数据。
success: function(data) {
在您的情况下,它将位于data
变量内。
我在你的控制器中看到你有这个:
format.js {
render json: {
html: render_to_string(
partial: 'city_stats',
locals: {
city_id: @city_id,
spatial_ratio: @spatial_ratio
})
}
}
所以你应该在你的处理程序中使用这些数据。可能是这样的:
success: function(data) {
$('#stats').empty().append(data.html);
}
但是,我不确定它在当前的实现中是否可以访问。我想每次你发出一个AJAX请求时,都会以
结束format.json { render :json => @cities }
因此,您应该返回@cities
并在此处呈现部分,并在相关的成功回调中使用它们,或者以某种方式为每个请求单独响应。
关于代码的另一件事 - 在$("#city_name")
的更改处理程序中绑定$("#city_state")
的事件处理程序并不好,因为在$("#city_state")
的每次更改时都添加了$("#city_name")
单击的相同处理程序,并且在每次单击时,此处理程序将被执行多次绑定。你可以在绑定之前使用.off来防止这种情况,但也许值得做一些重构。
答案 1 :(得分:1)
1.更新您的city_stats方法,如下所示
def city_stats
...
...
respond_to do |format|
format.json { render :json => @cities }
format.js
end
end
<强> 2。使用以下代码创建city_stats.js.erb文件
$("#stats").html("<%= escape_javascript(pie_chart @spatial_ratio.rows) %>");
第3。像这样更改你的city_click事件
$("#city_name").on('click', function(){
$.ajax({
url: "/admin/city_stats",
type: "GET",
data: {city: $(this).val()},
success: function(data) {
}
})
});
这应该可以解决您的问题。如果有任何问题/怀疑评论