symfony - Symfony 5 如何使用 jQuery ui 标签显示多个 Google 图表
问题描述
我的第一次 Symfony 5 尝试,我第一次尝试使用 Google Charts。我正在使用 CMENGoogleChartsBundle,它提供了一个 Twig 扩展和 PHP 对象来显示图表。
我想显示应该可以通过 jQuery UI 选项卡访问的不同图表我还有一个表格,其中显示了所有数据。例如,现在单击带有国家/地区的选项卡时,我希望更新图表和表格。我试图直接在我的树枝模板(fruitsoverview.html.twig)中显示所有数据,但是当单击一个选项卡时,我会在选项卡下方再次呈现页面,而且我会丢失任何可能的搜索过滤器设置,如果整个页面将被重新加载。然后我读到你可以只使用需要更新的内容创建一个视图,所以我已经这样做了,在我的控制器中我现在有:
if ($request->isXmlHttpRequest())
{
return $this->render('fruits/chart.html.twig', [
'searchFilter' => $searchFilter->createView(),
'fruitCounts' => $fruitCounts,
'barchart' => $barchart
]);
}else{
return $this->render('fruits/fruitsoverview.html.twig', [
'searchFilter' => $searchFilter->createView(),
'fruitCounts' => $fruitCounts,
'barchart' => $barchart
]);
}}
这解决了渲染问题,但未显示图表。图表数据在树枝视图中可用,但图表仅显示在默认选项卡上。我确实让表格显示了正确的数据。什么可能是错误的或更好的问题,它应该如何正确设置。我确信我还没有理解 Symfony 的概念,可能还没有理解 jQuery ui Tabs。任何帮助将不胜感激。非常感谢您提前。
更新
我现在已经更新了我的代码,并且除了条形图之外还可以部分工作。因此,表格的树枝变量在 AJAX 请求之后使用新内容进行更新,但条形图不会改变。我已经
在 chart.html.twig 中完成了 {{ dump(barchart) }} 并且我确实在其中得到了更新的数据,但图表没有重新绘制。我怎样才能做到这一点?
控制器
if ($request->isXmlHttpRequest())
{
$response = new JsonResponse();
$response->setStatusCode(200);
return new JsonResponse([
'html' => $this->renderView('fruits/chart.html.twig', [
'fruitCounts' => $fruitCounts,
'barchart' => $barchart
])
]);
在我的主模板中,我有以下代码和 Javascript。$("div#client-loop-container").html(data.html); 似乎更新了我的 chart.twig 模板中的 twig 变量。
<div id="client-loop-container">
{% include 'chart.html.twig' %}
</div>
{% block javascripts %}
{{ encore_entry_script_tags('app') }}
<script type="text/javascript">
$( function() {
$('#country-tabs a').on('click', function (e) {
e.preventDefault()
$(this).tab('show');
var $this = $(this),
loadurl = $this.attr('href');
var form = $('form');
var jsonData = $.ajax({
url: loadurl,
type: 'POST',
data: form.serializeArray(),
dataType: 'json',
success: function(data, status) {
$("div#client-loop-container").html(data.html);
}
}).responseText;
});
图表.html.twig
<div id="client-loop-container">
<div class="w-100" id="div_chart"></div>
<table class="table">
<tr>
<th>Date</th>
{% for fruitcount in fruitcounts %}
<th>{{ fruitcount }} </th>
{% endfor %}
</tr>
</table>
</div>
{% block javascripts %}
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
{{ gc_draw(barchart, 'div_chart') }}
</script>
{% endblock %}
解决方案
这是一个可能的解决方案。下面的代码使用单个<div>
来显示图表,但您可能能够适应选项卡和id="..."
解决方案。该方法用于jQuery.getScript()
运行特定于图表的 javascript。ChartService 使用 cmen/google-charts-bundle
来生成 javascript。该脚本由控制器响应提供给显示模板。可以显示六种不同的图表。该页面以伪轮播样式显示图表。
您可能会问,既然可以一次绘制所有六个图表并使用 javascript 一次隐藏和显示一个图表,那么为什么要这么麻烦。答案是图表 2 - n 通常不会显示所有选项。我开发了这个解决方案,以便垂直轴始终显示网格线上的值。
ChartService(为简洁起见,删除了图表定义):
namespace App\Service;
use App\Entity\RV;
use App\Entity\Summary;
use CMEN\GoogleChartsBundle\GoogleCharts\Options\VAxis;
use CMEN\GoogleChartsBundle\GoogleCharts\Charts\Histogram;
use CMEN\GoogleChartsBundle\GoogleCharts\Charts\LineChart;
use CMEN\GoogleChartsBundle\Twig\GoogleChartsExtension;
use Doctrine\ORM\EntityManagerInterface;
class ChartService
{
private $em;
private $gce;
public function __construct(EntityManagerInterface $em, GoogleChartsExtension $gce)
{
$this->em = $em;
$this->gce = $gce;
}
public function buildChart($chartType, $class, $subtype = null)
{
switch ($chartType) {
case 'line':
return $this->lineChart($class, $subtype);
break;
case 'histogram':
return $this->histoChart($class);
default:
break;
}
}
private function lineChart($class, $type)
{
...
return $chart;
}
private function histoChart($class)
{
...
return $histo;
}
public function getChartJs($chartSpecs, $location)
{
$chartType = $chartSpecs['type'] ?? null;
$class = $chartSpecs['class'] ?? null;
$subtype = $chartSpecs['subtype'] ?? null;
$chart = $this->buildChart($chartType, $class, $subtype);
$js = $this->getStart($chart, $location);
$end = $this->getEnd($chart, $location);
$part3 = substr($end, 0, strlen($end) - 1);
return $js . $end;
}
private function getStart($chart, $location)
{
return $this->gce->gcStart($chart, $location);
}
private function getEnd($chart, $location)
{
return $this->gce->gcEnd($chart, $location);
}
}
chartSwitch.js
$(document).ready(function () {
var i = $('#currentChart').attr('data-chart');
chartSwitch(i);
$('#chartNext').on('click', function () {
i++;
if (6 === i) {
i = 0;
}
chartSwitch(i);
});
$('#chartPrevious').on('click', function () {
i--;
if (-1 === i) {
i = 5;
}
chartSwitch(i);
});
function chartSwitch(i) {
$('#currentChart').attr('data-chart', i);
var url = "/js/" + i;
$.getScript(url);
}
});
控制器方法/js/ + i
/**
* @Route("/js/{which}", name="js")
*/
public function returnChartJs(ChartService $chart, $which)
{
$available = [
['type' => 'line', 'class' => 'C', 'subtype' => 'Price'],
['type' => 'line', 'class' => 'C', 'subtype' => 'Count'],
['type' => 'line', 'class' => 'B+', 'subtype' => 'Price'],
['type' => 'line', 'class' => 'B+', 'subtype' => 'Count'],
['type' => 'histogram', 'class' => 'C'],
['type' => 'histogram', 'class' => 'B+'],
];
$js = $chart->getChartJs($available[$which], 'chartA');
$response = new Response($js);
return $response;
}
显示模板的相关部分:
<div class="col-9 text-center">
<div class="row">
<div class="col-3"></div>
<div class="col-3">
<span id="currentChart" data-chart="0"></span>
<nav aria-label="Page navigation">
<ul class="pagination">
<li class="page-item">
<a id="chartPrevious" class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true">« Chart</span>
<span class="sr-only">Previous</span>
</a>
</li>
<li class="page-item">
<a id="chartNext" class="page-link" href="#" aria-label="Next">
<span aria-hidden="true">Chart »</span>
<span class="sr-only">Next</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
<div class="row">
<div class="col-12">
<div id="chartA"></div>
</div>
</div>
</div>
...
{% block javascripts %}
{{ parent() }}
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
{{ encore_entry_script_tags('charts') }}
{% endblock %}
推荐阅读
- assembly - Nasm - 乘以 2 个值时的奇怪结果
- python - hub.KerasLayer() 尽管 max_seq_len 发生变化,但总是消耗相同的 GPU 内存
- java - JNA 数组结构指针
- c++ - 尝试使用 Win32 WASAPI C++ 中的“捕获流”创建 wav 文件
- ios - 为什么我的初始 ViewController 只显示在模拟器 Hello World 上?
- timer - 如何用 ATL CAxDialogImpl 方法替换 MFC CDailog::OnTimer?
- python - 如何替换DataFrame(Python)中字符串列表中的字符串?
- javascript - JQuery 仅重新加载 div 数据
- javascript - 为什么此代码在之前工作时不起作用并为随机值添加按钮
- python - 为什么我在 SQL 语法中出现错误,无法将记录插入 MySQL 表 1064 (42000)?