我正在使用数据表和高图。我的目标是当用户单击按钮 2023、2022 和 ABC 按钮时,图表应重新加载以向用户提供动画效果。当我这样做时,我遇到了以下问题:
这是我的测试用例:https://codepen.io/Shawnny-Tandon/pen/bGJeOev
如果我将代码从 divID 更改为 tableID,它就可以工作。但是,图表只是加载而不提供动画。有什么解决办法吗?
$('#' + divId).DataTable().destroy(); 到 $('#' + tableId).DataTable().destroy();
function initializeDataTable(tableSelector) {
$(tableSelector).DataTable({
searching: false,
responsive: true,
lengthChange: false,
ordering: false,
info: false,
paging: false,
initComplete: function (settings, json) {
let api = new $.fn.dataTable.Api(settings);
var headers = api.columns().header().toArray();
headers.forEach(function (heading, index) {
if (index > 0 && index < headers.length) {
categories.push($(heading).html());
}
});
let rows = api.rows().data().toArray();
rows.forEach(function (row) {
group = {
name: '',
data: []
};
row.forEach(function (cell, idx) {
if (idx == 0) {
group.name = cell;
} else if (idx < row.length) {
group.data.push(parseFloat(cell.replace(/,/g, '')));
}
});
allSeriesData.push(group);
});
}
});
}
$(document).ready(function () {
if (typeof Highcharts !== 'undefined') {
initializeChart('demo-output', '#example1', 'test 1');
initializeChart('demo-output2', '#example', 'test 2');
var allSeriesData = [];
var categories = [];
$('#example2').data('scrollX-custom', true);
if (!$.fn.DataTable.isDataTable("#example2 table")) {
initializeDataTable("#example2 table");
}
Highcharts.setOptions({
lang: {
thousandsSep: ','
}
});
var myChart = Highcharts.chart("chart-A", {
chart: {
type: "column",
borderColor: 'lightgray',
borderWidth: 1,
marginTop: 50
},
tooltip: {
headerFormat: '{point.key}<br/>',
pointFormat: '{series.name}: <b>{point.y:.1f}%</b>'
},
legend: {
symbolRadius: 0,
itemStyle: {
color: '#000000',
fontSize: '16px'
}
},
colors: ['#003489', '#ED7D31', '#A5A5A5', '#FFC000', '#5B9BD5'],
credits: {
enabled: false
},
title: {
text: "test3"
},
xAxis: {
categories: categories,
labels: {
style: {
fontWeight: '600',
fontSize: '16px',
color: '#000000'
}
}
},
yAxis: {
title: false,
tickInterval: 10,
max: 60,
labels: {
formatter: function () {
return Highcharts.numberFormat(this.value, 0);
},
style: {
fontWeight: '600',
fontSize: '16px',
color: '#000000'
}
}
},
series: allSeriesData
});
$('#trend').on('click', function () {
$('#chart2').hide();
$('#chart1').hide();
$('#chart3').show();
reloadChart('chart-A', '#example2', 'Top Seven test Award Trends', 'chart-A', 'column');
$('.usa-button').removeClass('active');
$(this).addClass('active');
});
$('.usa-button').on('click', function () {
var buttonId = $(this).attr('id');
if (buttonId === 'previous') {
$('#chart2').show();
$('#chart1').hide();
$('#chart3').hide();
reloadChart('demo-output2', '#example', 'test Awards by NAICS Codes, FY 2022', 'demo-output2', 'pie');
} else if (buttonId === 'trend') {
} else {
$('#chart2').hide();
$('#chart1').show();
$('#chart3').hide();
reloadChart('demo-output', '#example1', 'test Awards by NAICS Codes, FY 2023', 'demo-output', 'pie');
}
$('.usa-button').removeClass('active');
$(this).addClass('active');
});
$('#current').addClass('active');
}
});
function initializeChart(chartId, tableId, chartTitle) {
const table = new DataTable(tableId, {
searching: false,
info: true,
paging: false,
sort: false
});
const chart = Highcharts.chart(chartId, {
chart: {
type: 'pie',
styledMode: false
},
title: {
text: chartTitle
},
colors: ['#1a4480', '#e52207', '#e66f0e', '#ffbe2e', '#fee685', '#538200', '#04c585', '#97d4ea', '#009ec1', '#0076d6', '#adadad', '#8168b3', '#d72d79', '#f2938c'],
tooltip: {
pointFormat: '</b> {point.y:.1f}%'
},
series: [{
data: chartData(table)
}],
credits: {
enabled: false
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
series: {
animation: {
duration: 2000
}
},
dataLabels: {
enabled: true,
format: '{point.y:.1f}%'
},
showInLegend: true
}
}
});
table.on('draw', function () {
chart.series[0].setData(chartData(table));
});
function chartData(table) {
var data = [];
table.rows().every(function () {
var row = this.data();
data.push({
name: row[0],
y: parseFloat(row[1])
});
});
return data;
}
}
function reloadChart(chartId, tableId, chartTitle, divId, chartType) {
$('#' + divId).DataTable().destroy();
const table = new DataTable(tableId, {
searching: false,
info: true,
paging: false,
sort: false
});
const chart = Highcharts.chart(chartId, {
chart: {
type: chartType,
styledMode: false
},
title: {
text: chartTitle
},
colors: ['#1a4480', '#e52207', '#e66f0e', '#ffbe2e', '#fee685', '#538200', '#04c585', '#97d4ea', '#009ec1', '#0076d6', '#adadad', '#8168b3', '#d72d79', '#f2938c'],
tooltip: {
pointFormat: '</b> {point.y:.1f}%'
},
series: [{
data: chartData(table)
}],
credits: {
enabled: false
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
series: {
animation: {
duration: 2000
}
},
dataLabels: {
enabled: true,
format: '{point.y:.1f}%'
},
showInLegend: true
}
}
});
table.on('draw', function () {
chart.series[0].setData(chartData(table), true);
});
function chartData(table) {
var data = [];
table.rows().every(function () {
var row = this.data();
data.push({
name: row[0],
y: parseFloat(row[1])
});
});
return data;
}
}
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<link href="https://nightly.datatables.net/css/dataTables.dataTables.css" rel="stylesheet" type="text/css" />
<script src="https://nightly.datatables.net/js/dataTables.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
</head>
<body>
<div class="ar-controls grid-row tablet:flex-justify-start">
<div class="tablet:grid-col-auto margin-bottom-205"><button id="current" class="usa-button usa-button--outline" title="Select to see related information below">2023</button> <button id="previous" class="usa-button usa-button--outline" title="Select to see related information below">2022</button> <button id="trend" class="usa-button usa-button--outline" title="Select to see related information below">ABC</button></div>
</div>
<div id="chart1">
<div id="demo-output" class="chart-display" style=" margin-bottom: 2em; height: 500px; border: solid 1px lightgray;"></div>
<table id="example1" class="display" style=" width: 100%;"><thead>
<tr>
<th scope="col">2023</th>
<th scope="col">Percent</th>
</tr>
</thead>
<tr>
<td scope="row">A</td>
<td>45.9%</td>
</tr>
<tr>
<td scope="row">B</td>
<td>22.0%</td>
</tr>
<tr>
<td scope="row">C</td>
<td>13.6%</td>
</tr>
</table>
</div>
<div id="chart2" style=" display: none;">
<div id="demo-output2" class="chart-display2" style=" margin-bottom: 2em; height: 680px; border: solid 1px lightgray;"></div>
<table id="example" class="display" style=" width: 100%;"><thead>
<tr>
<th scope="col">2022</th>
<th scope="col">Percent</th>
</tr>
</thead>
<tr>
<td>D</td>
<td>51.90%</td>
</tr>
<tr>
<td>E</td>
<td>18.60%</td>
</tr>
</table>
</div>
<div id="chart3" style=" display: none;">
<div id="chart-A" style=" width: 100%; height: 500px;"></div>
<table class="row-border stripe no-footer cell-border padding-top-5" id="example2" style=" width: 100%;"><thead>
<tr>
<th>Year</th>
<th>column1</th>
<th>column2</th>
<th>column3</th>
<th>column4/th>
<th>column5</th>
<th>column6</th>
<th>column7</th>
</tr>
</thead>
<tr>
<td scope="row" style=" text-align: left; white-space: nowrap;">FY19</td>
<td style=" text-align: left;">42.7%</td>
<td style=" text-align: left;">17.3%</td>
<td style=" text-align: left;">9.5%</td>
<td style=" text-align: left;">3.5%</td>
<td style=" text-align: left;">3.4%</td>
<td style=" text-align: left;">2.9%</td>
<td style=" text-align: left;">2.2%</td>
</tr>
</table>
</div>
</div>
背景
使用当前代码,您实际上会收到警告和错误。
当您尝试
destroy()
数据表时,会出现警告:
DataTables 警告:非表节点初始化 (DIV)。有关此错误的更多信息,请参阅https://datatables.net/tn/2
如技术说明链接中所述:
DataTables 将仅在 HTML 表格元素上初始化。
正如您在问题中所指出的,这就是为什么当您将
divId
更改为 tableId
时警告消失。
其次,因为表没有被销毁,所以您会收到后续错误,因为代码尝试初始化已经存在的表:
无法重新初始化DataTable。
一个解决方案
一个简单的解决方案是执行以下操作:
删除尝试破坏表的代码行:
// $('#' + divId).DataTable().destroy();删除此行
retrieve: true
选项(默认为 false
)。
此选项的工作原理如下:
如果表已经初始化,此参数将导致DataTables简单地返回已经设置的对象
这假设您的表的现有初始化参数可以重复使用。
在您的情况下,生成的代码是这样的:
function initializeDataTable(tableSelector) {
$(tableSelector).DataTable({
searching: false,
responsive: true,
lengthChange: false,
ordering: false,
info: false,
paging: false,
initComplete: function(settings, json) {
let api = new $.fn.dataTable.Api(settings);
var headers = api.columns().header().toArray();
headers.forEach(function(heading, index) {
if (index > 0 && index < headers.length) {
categories.push($(heading).html());
}
});
let rows = api.rows().data().toArray();
rows.forEach(function(row) {
group = {
name: '',
data: []
};
row.forEach(function(cell, idx) {
if (idx == 0) {
group.name = cell;
} else if (idx < row.length) {
group.data.push(parseFloat(cell.replace(/,/g, '')));
}
});
allSeriesData.push(group);
});
}
});
}
$(document).ready(function() {
if (typeof Highcharts !== 'undefined') {
initializeChart('demo-output', '#example1', 'test 1');
initializeChart('demo-output2', '#example', 'test 2');
var allSeriesData = [];
var categories = [];
$('#example2').data('scrollX-custom', true);
if (!$.fn.DataTable.isDataTable("#example2 table")) {
initializeDataTable("#example2 table");
}
Highcharts.setOptions({
lang: {
thousandsSep: ','
}
});
var myChart = Highcharts.chart("chart-A", {
chart: {
type: "column",
borderColor: 'lightgray',
borderWidth: 1,
marginTop: 50
},
tooltip: {
headerFormat: '{point.key}<br/>',
pointFormat: '{series.name}: <b>{point.y:.1f}%</b>'
},
legend: {
symbolRadius: 0,
itemStyle: {
color: '#000000',
fontSize: '16px'
}
},
colors: ['#003489', '#ED7D31', '#A5A5A5', '#FFC000', '#5B9BD5'],
credits: {
enabled: false
},
title: {
text: "test3"
},
xAxis: {
categories: categories,
labels: {
style: {
fontWeight: '600',
fontSize: '16px',
color: '#000000'
}
}
},
yAxis: {
title: false,
tickInterval: 10,
max: 60,
labels: {
formatter: function() {
return Highcharts.numberFormat(this.value, 0);
},
style: {
fontWeight: '600',
fontSize: '16px',
color: '#000000'
}
}
},
series: allSeriesData
});
$('#trend').on('click', function() {
$('#chart2').hide();
$('#chart1').hide();
$('#chart3').show();
reloadChart('chart-A', '#example2', 'Top Seven test Award Trends', 'chart-A', 'column');
$('.usa-button').removeClass('active');
$(this).addClass('active');
});
$('.usa-button').on('click', function() {
var buttonId = $(this).attr('id');
if (buttonId === 'previous') {
$('#chart2').show();
$('#chart1').hide();
$('#chart3').hide();
reloadChart('demo-output2', '#example', 'test Awards by NAICS Codes, FY 2022', 'demo-output2', 'pie');
} else if (buttonId === 'trend') {} else {
$('#chart2').hide();
$('#chart1').show();
$('#chart3').hide();
reloadChart('demo-output', '#example1', 'test Awards by NAICS Codes, FY 2023', 'demo-output', 'pie');
}
$('.usa-button').removeClass('active');
$(this).addClass('active');
});
$('#current').addClass('active');
}
});
function initializeChart(chartId, tableId, chartTitle) {
const table = new DataTable(tableId, {
searching: false,
info: true,
paging: false,
sort: false
});
const chart = Highcharts.chart(chartId, {
chart: {
type: 'pie',
styledMode: false
},
title: {
text: chartTitle
},
colors: ['#1a4480', '#e52207', '#e66f0e', '#ffbe2e', '#fee685', '#538200', '#04c585', '#97d4ea', '#009ec1', '#0076d6', '#adadad', '#8168b3', '#d72d79', '#f2938c'],
tooltip: {
pointFormat: '</b> {point.y:.1f}%'
},
series: [{
data: chartData(table)
}],
credits: {
enabled: false
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
series: {
animation: {
duration: 2000
}
},
dataLabels: {
enabled: true,
format: '{point.y:.1f}%'
},
showInLegend: true
}
}
});
table.on('draw', function() {
chart.series[0].setData(chartData(table));
});
function chartData(table) {
var data = [];
table.rows().every(function() {
var row = this.data();
data.push({
name: row[0],
y: parseFloat(row[1])
});
});
return data;
}
}
function reloadChart(chartId, tableId, chartTitle, divId, chartType) {
//$('#' + divId).DataTable().destroy( true );
const table = new DataTable(tableId, {
searching: false,
info: true,
paging: false,
sort: false,
retrieve: true
});
const chart = Highcharts.chart(chartId, {
chart: {
type: chartType,
styledMode: false
},
title: {
text: chartTitle
},
colors: ['#1a4480', '#e52207', '#e66f0e', '#ffbe2e', '#fee685', '#538200', '#04c585', '#97d4ea', '#009ec1', '#0076d6', '#adadad', '#8168b3', '#d72d79', '#f2938c'],
tooltip: {
pointFormat: '</b> {point.y:.1f}%'
},
series: [{
data: chartData(table)
}],
credits: {
enabled: false
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
series: {
animation: {
duration: 2000
}
},
dataLabels: {
enabled: true,
format: '{point.y:.1f}%'
},
showInLegend: true
}
}
});
table.on('draw', function() {
chart.series[0].setData(chartData(table), true);
});
function chartData(table) {
var data = [];
table.rows().every(function() {
var row = this.data();
data.push({
name: row[0],
y: parseFloat(row[1])
});
});
return data;
}
}
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<link href="https://nightly.datatables.net/css/dataTables.dataTables.css" rel="stylesheet" type="text/css" />
<script src="https://nightly.datatables.net/js/dataTables.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
</head>
<body>
<div class="ar-controls grid-row tablet:flex-justify-start">
<div class="tablet:grid-col-auto margin-bottom-205"><button id="current" class="usa-button usa-button--outline" title="Select to see related information below">2023</button> <button id="previous" class="usa-button usa-button--outline" title="Select to see related information below">2022</button>
<button
id="trend" class="usa-button usa-button--outline" title="Select to see related information below">ABC</button>
</div>
</div>
<div id="chart1">
<div id="demo-output" class="chart-display" style=" margin-bottom: 2em; height: 500px; border: solid 1px lightgray;"></div>
<table id="example1" class="display" style=" width: 100%;">
<thead>
<tr>
<th scope="col">2023</th>
<th scope="col">Percent</th>
</tr>
</thead>
<tr>
<td scope="row">A</td>
<td>45.9%</td>
</tr>
<tr>
<td scope="row">B</td>
<td>22.0%</td>
</tr>
<tr>
<td scope="row">C</td>
<td>13.6%</td>
</tr>
</table>
</div>
<div id="chart2" style=" display: none;">
<div id="demo-output2" class="chart-display2" style=" margin-bottom: 2em; height: 680px; border: solid 1px lightgray;"></div>
<table id="example" class="display" style=" width: 100%;">
<thead>
<tr>
<th scope="col">2022</th>
<th scope="col">Percent</th>
</tr>
</thead>
<tr>
<td>D</td>
<td>51.90%</td>
</tr>
<tr>
<td>E</td>
<td>18.60%</td>
</tr>
</table>
</div>
<div id="chart3" style=" display: none;">
<div id="chart-A" style=" width: 100%; height: 500px;"></div>
<table class="row-border stripe no-footer cell-border padding-top-5" id="example2" style=" width: 100%;">
<thead>
<tr>
<th>Year</th>
<th>column1</th>
<th>column2</th>
<th>column3</th>
<th>column4/th>
<th>column5</th>
<th>column6</th>
<th>column7</th>
</tr>
</thead>
<tr>
<td scope="row" style=" text-align: left; white-space: nowrap;">FY19</td>
<td style=" text-align: left;">42.7%</td>
<td style=" text-align: left;">17.3%</td>
<td style=" text-align: left;">9.5%</td>
<td style=" text-align: left;">3.5%</td>
<td style=" text-align: left;">3.4%</td>
<td style=" text-align: left;">2.9%</td>
<td style=" text-align: left;">2.2%</td>
</tr>
</table>
</div>
</div>
</body>
</html>