问题
I have a page which I am trying to show multiple NVD3 charts on tabs. I see on the NVD3 site that they store all chart names ahead of time but I am not sure how I should do this.
I have graph models which get stored in the database and then my page must dynamically render all of the charts and appropriate javascript on the fly. So far only the last graph constructed shows :(
I render this partial for each graph
<%if graph.present?%>
<%@graph = graph%>
<%end%>
<%if @graph.data.empty?%>
<%= render 'graphs/no_graph'%>
<%else%>
<script type="text/javascript">
$(document).ready(function() {
var data = $('#chart_<%=@graph.id%>').data('data');
reloadGraph(data);
$('a[data-toggle="tab"]').on('shown', function(e) {
reloadGraph(data)
})
})
function reloadGraph(data) {
nv.addGraph(function() {
var chart = nv.models.multiBarChart();
chart.yAxis.axisLabel('Monthly (kWh)');
d3.select('#chart_<%=@graph.id%> svg').datum(data).transition().duration(500).call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
}
</script>
<%=content_tag :div, id: "chart_#{@graph.id}",class: 'chart', data: {data: graph.monthly_data} do%>
<svg></svg>
<%end%>
<%end%>
On the NVD3 site they start off with:
var MainExample, ExampleOne, Example2
etc.
Then in their constuction call they assign e.g. MainExample = chart
Any advice on how I should structure this in rails??
回答1:
Ok so there were no takers on answering here but basically it turns out that you have to store the dynamic objects in an array like
var charts = []
Then loop through the charts with a each_with_index
and use the index to reference the various charts
in your each_with_index
loop which is essentially rendering out the javascript a piece at a time, you render out the creation of each dynamic graph.
Mine looked like this (un-polished but working fine)
<script type="text/javascript">
var graphs = []
var data = []
$(document).ready(function(){
/*Render out the bargraphs js*/
<%graphs.each_with_index do |graph, index|%>
data[<%=index%>] = $('#chart_<%= graph.id%>').data('data');
nv.addGraph(function() {
<%if graph.type == "BarGraph"%>
var chart = nv.models.multiBarChart().margin({left: 80, bottom: 30});
<%else%>
var chart = nv.models.lineChart().margin({left: 80, bottom: 30});
chart.xAxis
.tickFormat(function(d) { return d3.time.format('%H:%M')(new Date(d)); })
<%end%>
chart.yAxis
.axisLabel('kVA')
d3.select('#chart_<%= graph.id%> svg')
.datum(data[<%=index%>])
.transition()
.duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
graphs[<%=index%>] = chart
return chart;
});
<%end%>
$('a[data-toggle="tab"]').on('shown', function(e) {
$.each(graphs, function(index, graph){
graph.update()
})
})
})
</script>
<div class="row-fluid">
<div class="span12">
<ul class="nav nav-tabs" id="graph_tabs">
<%graphs.each_with_index do |graph, index|%>
<li <%= index == 0 ? "class=active" : ''%>>
<a href="#graph_tab_<%= graph.id%>" data-toggle="tab">
<%= graph.description%>
</a>
</li>
<%end%>
</ul>
<div class="tab-content">
<%graphs.each_with_index do |graph, index|%>
<div id='graph_tab_<%=graph.id%>' class="tab-pane fade <%= index == 0 ? "active in" : ''%>">
<%=render "graphs/#{graph.type.downcase}", graph:graph%>
</div>
<%end%>
</div>
</div>
</div>
The funny bit at the end is a very handy trick to get the graphs to re render when you are using bootstrap tabs otherwise they don't render properly.
来源:https://stackoverflow.com/questions/17222968/dynamic-creation-of-multiple-nvd3-charts-with-rails-partial