如何解决使用响应式布局的制表器渲染问题
问题: 如果我坚持使用布局,那么几乎所有东西都可以工作:“ fitColumns”我尝试的任何其他操作似乎都会导致渲染(如果这是正确的术语)问题。我没有使用框架(在时间范围内过桥)。当页面完全加载后显示表格时,无论我选择哪种布局-它总是像“ fitColumns”一样开始显示。例如,如果我将其设置为“ fitDataFill”,它将加载并显示为“ fitColumns”。当我单击另一个选项卡并再次返回时 然后显示适合fitDataFill的数据。
修订:
大致步骤:
- 加载一个特定的文件,其中包含有关要加载到表中的其余文件的元数据,这些表的名称,每个表中的列以及在列标题上显示为浮点式帮助的文本
- 加载其余数据并构建包含元数据的表配置对象
- 为每个表添加特定于表的div,并将其附加到csv-tab-buttons div
- 在新创建的div上构建表
- 添加按钮,该按钮将切换通过css活动类和setTab函数显示哪个表
如果您看到的代码类似于您在此处编写的代码,那么感谢您,我从他人那里收集了我写的大部分内容。
制表器版本为4.8 使用Visual Studio Code创建代码,使用Live Server扩展在每次保存后重新加载页面 浏览器是Chrome版本85.0.4183.121(正式版本)(64位)
- 我根据@mirza的建议进行了改写,以确保在构建表之前完全读取数据,并且每个表都独立存储,因此我不会每次都将同一表传递给setTab
- fitColumns有效,但不允许我单独调整列的大小(可能是设计使然)
- fitData似乎可以正常工作
- fitDataFill和fitDataStretch在同一个表格的第一个渲染或后续渲染上不起作用,直到我单击并再次返回
- 我试图通过调试器遵循tabulator.js中的逻辑,尽管我可以看到正在发生的事情,但是其中发生了太多的事情让我无法把握问题的可能所在
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<Meta charset="UTF-8" />
<Meta name="viewport" content="width=device-width,initial-scale=1.0" />
<Meta http-equiv="X-UA-Compatible" content="ie=edge" />
<!-- CSS -->
<link rel="stylesheet" href="./scripts/dist/css/tabulator.min.css">
<link rel="stylesheet" href="./styles/style.css">
<!-- Scripts -->
<script type="text/javascript" src="./scripts/dist/js/tabulator.min.js"></script>
<script type="text/javascript" src="./scripts/dist/js/papaparse.min.js"></script>
<title>My Team</title>
</head>
<body>
<!-- Wrapper -->
<div class="wrapper">
<section class="container">
<!-- Header -->
<header id="header" class="header">
<h1>Reporting</h1>
</header>
<!-- Tabs -->
<div id="csv-tab-buttons" class="tab">
</div>
<!-- Tables on each tab -->
<div id="csv-tabs">
</div>
<!-- Footer -->
<footer class="footer">
<p>My Team © 2020</p>
</footer>
</section>
</div><!-- Wrapper Ends-->
<script src="./scripts/dist/js/miscsv.min.js"></script>
</body>
</html>
修订的Javascript:
//*******************************************************************************************************
// Global variables
//*******************************************************************************************************
var file = 'DS.PPTE.DB2.VIaraCF.VARLEGND.CSV'
var tables = []
var tableDivs = []
var tabConfig = {}
//*******************************************************************************************************
// Global functions
//*******************************************************************************************************
let onlyUnique = (value,index,self) => {
return self.indexOf(value) === index
}
//*******************************************************************************************************
// Async functions
//*******************************************************************************************************
// Set the tab to whichever button was clicked
async function activateTab(target) {
// hides all tabs
document.querySelectorAll(".tabcontent").forEach(tabContent => tabContent.style.display = "none");
// Remove the active class from all tab links
document.querySelectorAll('.tablinks').forEach(tabLink => tabLink.className.replace("active",""));
// Remove the active class from the active tab
document.querySelectorAll(".active").forEach(activeTab => activeTab.classList.remove("active"))
// Activate the selected tab
document.querySelector(`#${target.textContent}`).style.display = "block"
target.classList.add("active");
}
async function setTab(target) {
console.log("Activate the tab")
await activateTab(target)
console.log("Redraw the table")
// Redraw the table
tableDivs[`${target.textContent}`].redraw(true);
}
// Read a CSV file
const readCSV = async (file) => {
return new Promise(resolve => {
Papa.parse(`data/${file}`,{
header: true,download: true,skipEmptyLines: true,complete: results => {
console.log(`${file} loaded - ${results.data.length} records.`)
resolve(results)
}
})
})
}
// Get all the data first
async function getData() {
// Read the Meta data file with the data and table config
let parseMeta = await readCSV(file)
tabConfig = {
// Get the names of the tables to present
tabs: parseMeta.data.map((data) => data['TABLE-NAME']).filter(onlyUnique).sort(),// Find the file name for each table
files: parseMeta.data.map((data) => `${data['TABLE-NAME']}-${data['CSV-FILE-NAME']}`).filter(onlyUnique)
.map((entry) => {
let tmpEntry = entry.split('-')
return { table: `${tmpEntry[0]}`,file: `${tmpEntry[1]}` }
}),// Save the float over help for each column by table name
help: parseMeta.data.map((data) => {
return { key: `${data['TABLE-NAME']}-${data['VARIABLE']}`,helpText: data['VAR-DESCRIPTION'] != '' ? data['VAR-DESCRIPTION'] : data['VARIABLE'] }
}),data: tables,divs: tableDivs,}
// Read in the files which contain the table data
for (const tabName of tabConfig.tabs) {
let file = tabConfig.files.filter(entry => entry.table == tabName)[0].file
tables[tabName] = await readCSV(file)
tableDivs[tabName] = `csv-table-${tabName}`
}
}
// Master function to do everything in the right order
async function doAll() {
// Get all the data and build the table config
await getData()
// Store the buttons and tabs anchor divs
let buttonsDiv = document.getElementById("csv-tab-buttons")
let tabsDiv = document.getElementById("csv-tabs")
// Add the buttons and tables
for ([idx,tabName] of tabConfig.tabs.entries()) {
// Add tabs to hold the tables to the page
const elemTabDiv = document.createElement('div')
const elemTableDiv = document.createElement('div')
elemTabDiv.id = tabName
elemTabDiv.className = "tabcontent"
elemTableDiv.id = `csv-table-${tabName}`
elemTableDiv.className = "table"
elemTabDiv.appendChild(elemTableDiv)
tabsDiv.appendChild(elemTabDiv)
// Define header context menu
let headerMenu = [
{
label:"Hide Column",action:function(e,column){
column.hide()
},},]
// Create the table
tableDivs[tabName] = new Tabulator(`#csv-table-${tabName}`,{
data:tabConfig.data[tabName].data,layout:"fitData",responsiveLayout:"collapse",tooltips:true,pagination:"local",paginationSize:20,resizableColumns:true,movableColumns:true,resizableRows:true,autoColumns: true,autoColumnsDeFinitions: function(deFinitions) {
deFinitions.forEach((column) => {
let helpText = tabConfig.help.find(key => key.key === `${tabName}-${column.field}`).help
// Add float over help based on column name
column.headerTooltip = helpText
column.headerMenu = headerMenu
column.headerFilter = true
column.headerSort = true
column.headerFilterLiveFilter = false
})
return deFinitions
},renderStarted:function(){
console.log("Render started")
},renderComplete:function(){
console.log("Render complete")
},})
// Add tab buttons to page
const elemTabButton = document.createElement('button')
elemTabButton.id = `button-${tabName}`
if ( idx == 0 ) {
elemTabButton.className = "tablinks active"
} else {
elemTabButton.className = "tablinks"
}
elemTabButton.onclick = function() { setTab(this) }
elemTabButton.textContent = tabName
buttonsDiv.appendChild(elemTabButton)
}
document.querySelector(".active").click();
}
doAll()
CSS:
:root {
--shadow: 0 1px 5px rgba(104,104,0.8);
--raisin: #262730;
--vermillion: #d33f49;
--cadet: #576c75;
--navyboy: #8db2c2;
--space-cadet: #363457;
--baby-powder: #f0f4ef;
--ice: rgb(245,247,253);
}
html {
Box-sizing: border-Box;
font-family: Arial,Helvetica,sans-serif;
color: var(--dark);
}
body {
background: var(--baby-powder);
margin: 10px 10px;
line-height: 1.4;
}
/* .wrapper {
display: grid;
grid-gap: 10px;
} */
.container {
display: grid;
grid-gap: 10px;
grid-template-areas:
'header'
'csv-tab-buttons'
'footer';
margin: auto;
width: 98%;
overflow: auto;
padding: 1rem 1rem;
}
header {
background: var(--raisin);
color: var(--vermillion);
font-size: 150%;
line-height: 1;
padding: 0.1rem;
text-align: center;
Box-shadow: var(--shadow);
}
.tab {
background-color: var(--ice);
Box-shadow: var(--shadow);
}
/* Style the buttons that are used to open the tab content */
.tab button {
background-color: inherit;
/* float: left; */
border: none;
outline: none;
cursor: pointer;
/* padding: 14px 16px; */
padding: 1rem 1.1rem;
transition: 0.3s;
}
/* Change background color of buttons on hover */
.tab button:hover {
background-color: var(--cadet);
color: var(--ice);
}
/* Create an active/current tablink class */
.tab button.active {
background-color: var(--vermillion);
color: var(--ice);
}
/* Style the tab content */
.tabcontent {
/* overflow: hidden; */
display: none;
/* padding: 6px 12px; */
/* border-top: none; */
}
/* Override Tabulator header background */
.tabulator-col-content {
background-color: var(--ice);
}
.table {
overflow: hidden;
Box-shadow: var(--shadow);
}
.footer {
background: var(--cadet);
color: white;
padding: 0rem 2rem;
line-height: 1;
Box-shadow: var(--shadow);
}
编辑: 我对所有顺序进行了一些更改,以便在调用 setTab 函数时可以将表对象保持在范围内,并且在单击选项卡按钮时可以发出重绘。第一次单击每个选项卡时,它似乎填充了数据的宽度。当我再次单击每个选项卡时,它将正确包裹将不在屏幕上的列换行到下一行。我在setTab例程中放置了多个表重绘,这对表的呈现没有影响。但是,它确实以某种方式更改了表的属性。我在调试器中观察到,tableWidth从第一次重绘之前的0更改为2734,在第二次重绘之后更改为2786,并保持在该值。如果我单击鼠标左键并再次返回,它会按预期包裹。
解决方法
如果在创建表时该元素不可见,则无法正确显示制表器表。
要正确渲染表格,必须在元素可见时重新绘制表格。
请参见Here
从网站上:
如果包含制表符的元素的大小发生了变化(并且您无法使用内置的自动调整大小功能),或者在其包含元素可见之前创建了表,则必须重新绘制该表才能确保行和列正确呈现。
您可以通过以下方式重绘表格
table.redraw();
或
table.redraw(true); //trigger full rerender including all data and rows
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。