Complex header column titles as ladders in child rows created by responsive
Complex header column titles as ladders in child rows created by responsive
Description of problem:
I am using the pandas.DataFrame.to_html
method, which you can find here. My backend is Flask so I can use Pandas.
Since it creates the HTML code of the dataframe in execution, aspects such as the style of the table are managed with the classes
parameter. What you can see in the return
you can see how I have put the responsive directly with dt-responsive nowrap
and a custom CSS table-style
which I will talk about later, plus Bootstrap 5 styles.
In my backend there is this:
#PYHTON-FLASK
my_dict = {
' ': {'Tecnología': ['PROSA', 'JAVA', 'C', 'JAVA', 'PROSA', 'C', 'Python'],
'Tipo de cambio': ['Correctivo', 'Nuevo', 'Nuevo', 'Evolutivo', 'Evolutivo', 'Correctivo', 'Correctivo'],
'Metodología': ['Waterfall', 'Agile', 'Waterfall', 'Agile', 'Waterfall', 'Agile', 'Agile'],
'Centro': ['TGSS', 'INSS', 'GISS', 'ISM', 'ISM', 'GISS', 'INSS'],
'Lote': ['LOTE6', 'LOTE6', 'LOTE6', 'LOTE4', 'LOTE5', 'LOTE4', 'LOTE5'],
'Aplicación': ['RASS', 'ACAR', 'TRHA', 'SIGE', 'GEMA', 'FRIN', 'RARI'],
'Version': ['01.12.16', '01.12.16', '01.02.03', '03.12.16', '01.14.16', '01.00.16', '01.12.20']},
'Pruebas de vulnerabilidad': {'Recomendación': ['SI', 'NO', 'NO', 'NO', 'SI', 'SI', 'SI'],
'Decisión': ['SI', 'SI', 'PDTE', 'SI', 'SI', 'NO', 'PDTE']},
'Pruebas de accesibilidad': {'Recomendación': ['SI', 'NO', 'NO', 'NO', 'SI', 'SI', 'SI'],
'Decisión': ['SI', 'SI', 'PDTE', 'SI', 'SI', 'NO', 'PDTE']},
'Pruebas de rendimiento': {'Recomendación': ['SI', 'NO', 'NO', 'NO', 'SI', 'SI', 'SI'],
'Decisión': ['SI', 'SI', 'PDTE', 'SI', 'SI', 'NO', 'PDTE']},
'Pruebas funcionales': {'Excepciones CONF predichas': ['0-0.4', '0.4-1', '1+', '0.5-0.9', '0.3-1', '1+', '0.1-0.2'],
'Excepciones DEV predichas': ['0.5-3', '0.5-3', '3+', '1+', '0.5-1', '2+', '0.6-3'],
'Decisión': ['SI', 'SI', 'PDTE', 'SI', 'SI', 'NO', 'PDTE']}
}
reform = {(level1_key, level2_key): values
for level1_key, level2_dict in my_dict.items()
for level2_key, values in level2_dict.items()
}
df = pd.DataFrame(reform)
return render_template('template.html', data=df.to_html(index=False, justify='center', classes=['table', 'table-striped', 'table-bordered', 'table-hover', 'table-condensed', 'dt-responsive nowrap','table-style'], table_id='ultimoAnalisis'))
And in the future I will receive tables from a SQL Server that I will have to pass to a dataframe to make some modifications. That is why I have harcoded an exact dataframe with 7 rows for testing.
In order to create a table with a complex header I had to create the dictionary that way. At first you can see that I put several simple columns inside an empty complex column. This is basically so that the code immediately following the dictionary works and creates a dataframe with a complex header.
Another problem that I found is that logically I could not paint the headers, and that I could not justify the text of the entire table in the center since when I put:
columnDefs: [
{
targets:"_all",
className: 'dt-center'
},
the JavaScript part was focused on everything except the complex header content.
On the other hand, the .to_html
method put a
style="width: 1800px;"
in the <table>
tag that got into the ```element.style{ width: 1800px;}. This caused the responsiveness of the table to not work well.
To fix these 3 things (header color, center-justify complex header text and fix responsiveness) create a CSS template with this:
.table-style thead {
background-color: #5f5f5f;
color: #fff;
text-align:center;
}
.table-style {
width: 100% !important;
}
My template.html currently looks like this (removing the imports and a <nav>
):
<div style="margin-left: 0.9%; margin-right: 0.9%">
{{data | safe}}
</div>
{{data | safe}}
it's how Jinja2 saves things returned to it from the backend (roughly). You can see more here. This is where the HTML generated by .to_html
will be pasted.
<script>
$(document).ready(function () {
$("#ultimoAnalisis").DataTable({ //Parte DataTable
language: {//Pone en español todo lo referente a datatables
url: "../static/dataTables/es-ES.json"
},
searchPanes: { //Activa los filtros
cascadePanes: true, //Activa filtros en cascada
viewTotal: true, //Muestra el total de registros en los filtros
initCollapsed: true, //Filtros cerrados de manera inicial
order: [//Orden de los filtros
"Centro",
"Lote",
"Aplicación",
"Tecnología",
"Tipo de cambio",
"Metodología",
],
},
dom: "Plfrtip",
columnDefs: [
{
//Alineamos el texto de las columnas en el centro en la zona de filas. (En el caso de las cabeceras se controla por CSS en tabla.css)
targets:"_all",
className: 'dt-body-center'
},
{
//Ocultar las filtros de: 'Version', 'Pruebas de vulnerabilidad','Pruebas de accesibilidad','Pruebas de rendimiento','Pruebas de funcionales'
targets: [6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
searchPanes: {
show: false,
},
},
{
//Forzar a que se muestren los filtros de la columna 'Aplicación'
targets: [5],
searchPanes: {
show: true,
},
},
{
//Ocultar las columnas: 'Centro', 'Lote','Tecnología','Tipo de cambio','Metodología'
targets: [0, 1, 2, 3, 4],
visible: false,
},
],
});
});
</script>
El resultado de mi tabla es este:
But when it comes to responsiveness, look at this video that I made in 20 seconds. (Sorry about the music... I recorded with Windows+G and I thought I was listening to music).
So several questions:
- What happens in the second 12 can be fixed.
- During the video you can see how childrows are created as they are hidden. In them appears the name of the column in bold and the value. But the name of the complex column does not appear anywhere. That is, I want it to look something like this (I make a sketch with colors):
THANKS
Answers
Without seeing, it's hard to say if there's a quick fix. I suspect the issue is the
colspan
header cells. It would be worth looking at our Responsive plugin, as that does something similar, but again, that wouldn't support the double header rows withcolspan
,Colin
Yes, that is the extension I am using. I activate it by passing
dt-responsive nowrap
to<table>
with theclasses
parameter to.to_html
. You can see it in thereturn
of the first block of code in my post (line 27).Here you can see some of the code that generates
.to_html
, in this case the table part. On line 10 is the complex header part and on line 18 is the simple header part:I have seen this: responsive.details.display, and I think it is the solution, but I don't know how to approach it.
Regarding what happens in the video, in the second 12, nothing can be done, right?
Thanks Colin.
As Colin mentioned the Responsive extension doesn't support complex headers with
colspan
. However you probably could use theresponsive-resize
event to manage thethead
rows that Responsive doesn't support. Use thecolumn
parameter to see which columns are hidden then, based on your requirements, you can hide or display the columns withcolspan
.Kevin