[英]Div is not updated after selecting value on a dropdown list
I'm trying to display a chart upon selecting a state and a city.我试图在选择州和城市时显示图表。
The cities dropdown list is populated based on the selection of the state in the first dropdown.城市下拉列表是根据第一个下拉列表中的州选择填充的。
The problem is when I click on a city no chart is displayed, nor updated if I change the selection, and I can't seem to figure out the problem.问题是当我点击一个城市时,没有图表显示,如果我改变选择也没有更新,我似乎无法弄清楚问题所在。
I'm using ChartKick to display a pie chart with the values given by a query in the controller.我正在使用 ChartKick 显示一个饼图,其中包含控制器中查询给出的值。
My code is as follows:我的代码如下:
controllers/city_stats_controller.rb:控制器/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 :视图/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;
}
})
})
}
})
});
});
And in the partial : views/city_stats/_city_stats.html.erb :在部分: views/city_stats/_city_stats.html.erb :
<%= pie_chart @spatial_ratio.rows %>
NB : If I replace the city_id in the dynamic query in the controller by a random id manually, a chart is displayed of the corresponded city when I refresh the page, but I don't know why it's not working dynamically注意:如果我手动将控制器中动态查询中的 city_id 替换为随机 id,刷新页面时会显示对应城市的图表,但我不知道为什么它不能动态工作
@city_id = City.select('id').find_by_id(params[:city])
This line doesn't return you a number.这一行不会返回一个数字。 It returns an instance of your model with only one field (id) loaded.
它返回一个只加载了一个字段 (id) 的模型实例。 Try to change it to
尝试将其更改为
@city_id = City.select('id').find_by_id(params[:city]).id
That will give you a number.那会给你一个数字。
Also, as I see, in your handler of AJAX in $("#city_name").on('click')
you don't actually update your view with generated chart.此外,正如我所见,在
$("#city_name").on('click')
的 AJAX 处理程序中,您实际上并未使用生成的图表更新视图。
<%= j render(partial: 'city_stats') %>
This line gets evaluated only once, on initial rendering of the html page (that's why everything works when city_id
is set manually), so on each AJAX request, that doesn't reload your page entirely, you replace $('#stats')
with the same content.此行仅在 html 页面的初始呈现时评估一次(这就是手动设置
city_id
时一切正常的原因),因此在每个 AJAX 请求中,不会完全重新加载您的页面,您替换$('#stats')
具有相同的内容。
By the way, once you replace $('#stats')
, you will not access it the next time without total rerendering of the page, because it gets removed from the DOM.顺便说一句,一旦您替换了
$('#stats')
,您将不会在没有完全重新呈现页面的情况下下次访问它,因为它已从 DOM 中删除。 See reference of ( replaceWith ).请参阅 ( replaceWith ) 的参考。
I think that in case of AJAX it's better to use .empty() on $('#stats')
container and then .append() new chart inside it.我认为在 AJAX 的情况下,最好在
$('#stats')
容器上使用.empty()然后在其中使用.append()新图表。
The idea is that if you want to update chart without reloading of the page, you should use the fresh data from the the server.这个想法是,如果你想在不重新加载页面的情况下更新图表,你应该使用来自服务器的新数据。
success: function(data) {
In your case it will be inside the data
variable.在您的情况下,它将在
data
变量内。
I see that in your controller you have this:我看到在你的控制器中你有这个:
format.js {
render json: {
html: render_to_string(
partial: 'city_stats',
locals: {
city_id: @city_id,
spatial_ratio: @spatial_ratio
})
}
}
So you should use this data in your handler.所以你应该在你的处理程序中使用这些数据。 It might be like this:
它可能是这样的:
success: function(data) {
$('#stats').empty().append(data.html);
}
However, I'm not sure that it's reachable in current implementation.但是,我不确定它在当前实现中是否可以访问。 I guess that every time you make an AJAX request, it will end with
我猜每次你发出 AJAX 请求时,它都会以
format.json { render :json => @cities }
So you should either return both @cities
and rendered partial here, and use them in relevant success callbacks, or somehow separate responses for each request.因此,您应该在此处返回
@cities
和渲染部分,并在相关的成功回调中使用它们,或者以某种方式将每个请求的响应分开。
One more thing about the code - it's not good to bind event handler for $("#city_name")
inside change handler of $("#city_state")
, because on every change of $("#city_state")
you add the same handler for $("#city_name")
click, and on each click this handler will be executed as many times as it has been bound.关于代码的另一件事 - 在
$("#city_state")
更改处理程序中绑定$("#city_name")
事件处理程序不好,因为在$("#city_state")
每次更改中添加相同的$("#city_name")
单击的处理程序,每次单击时,此处理程序将执行与绑定的次数相同的次数。 You can use .off before binding to prevent this, but maybe it's worth to do some refactoring.您可以在绑定之前使用.off来防止这种情况发生,但也许值得进行一些重构。
1.update your city_stats method like below 1.更新您的 city_stats 方法,如下所示
def city_stats
...
...
respond_to do |format|
format.json { render :json => @cities }
format.js
end
end
2. create city_stats.js.erb file with below code 2. 使用以下代码创建 city_stats.js.erb 文件
$("#stats").html("<%= escape_javascript(pie_chart @spatial_ratio.rows) %>");
3. change your city_click event like this 3.像这样改变你的city_click事件
$("#city_name").on('click', function(){
$.ajax({
url: "/admin/city_stats",
type: "GET",
data: {city: $(this).val()},
success: function(data) {
}
})
});
This should solve your problem.这应该可以解决您的问题。 If any problem/doubt comment
如果有任何问题/疑问评论
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.