Are you ready for this?
Check this out, this will support sorting and filters:
app.py
import dash_ag_grid as dag
from dash import Dash, html, Output, Input
app = Dash(__name__)
data = [
{
'localTime': '5:00am',
'show': {'name': 'Wake Up Dublin', 'presenter': 'Andrew Connell'},
'a': 0.231, 'b': 0.523, 'c': 0.423, 'd': 0.527,
},
{'localTime': '5:15am',
'show': {'name': 'Wake Up Dublin', 'presenter': 'Andrew Connell'},'a': 0.423, 'b': 0.452, 'c': 0.523, 'd': 0.543},
{'localTime': '5:30am', 'show': {'name': 'Wake Up Dublin', 'presenter': 'Andrew Connell'},'a': 0.537, 'b': 0.246, 'c': 0.426, 'd': 0.421},
{'localTime': '5:45am', 'show': {'name': 'Wake Up Dublin', 'presenter': 'Andrew Connell'},'a': 0.893, 'b': 0.083, 'c': 0.532, 'd': 0.983},
{
'localTime': '6:00am',
'show': {'name': 'Pure Back In The Day', 'presenter': 'Kevin Flanagan'},
'a': 0.231, 'b': 0.523, 'c': 0.423, 'd': 0.527,
},
{'localTime': '6:15am', 'a': 0.423, 'b': 0.452, 'c': 0.523, 'd': 0.543, 'show': {'name': 'Pure Back In The Day', 'presenter': 'Kevin Flanagan'},},
{'localTime': '6:30am', 'a': 0.537, 'b': 0.246, 'c': 0.426, 'd': 0.421, 'show': {'name': 'Pure Back In The Day', 'presenter': 'Kevin Flanagan'},},
{'localTime': '6:45am', 'a': 0.893, 'b': 0.083, 'c': 0.532, 'd': 0.983, 'show': {'name': 'Pure Back In The Day', 'presenter': 'Kevin Flanagan'},},
{
'localTime': '7:00am',
'show': {'name': 'The Queens Breakfast', 'presenter': 'Tony Smith'},
'a': 0.231, 'b': 0.523, 'c': 0.423, 'd': 0.527,
},
{'localTime': '7:15am', 'a': 0.423, 'b': 0.452, 'c': 0.523, 'd': 0.543, 'show': {'name': 'The Queens Breakfast', 'presenter': 'Tony Smith'},},
{'localTime': '7:30am', 'a': 0.537, 'b': 0.246, 'c': 0.426, 'd': 0.421, 'show': {'name': 'The Queens Breakfast', 'presenter': 'Tony Smith'},},
{'localTime': '7:45am', 'a': 0.893, 'b': 0.083, 'c': 0.532, 'd': 0.983, 'show': {'name': 'The Queens Breakfast', 'presenter': 'Tony Smith'},},
{
'localTime': '8:00am',
'show': {'name': 'Cosmetic Surgery', 'presenter': 'Niall Crosby'},
'a': 0.231, 'b': 0.523, 'c': 0.423, 'd': 0.527,
},
{'localTime': '8:15am', 'a': 0.423, 'b': 0.452, 'c': 0.523, 'd': 0.543, 'show': {'name': 'Cosmetic Surgery', 'presenter': 'Niall Crosby'},},
{'localTime': '8:30am', 'a': 0.537, 'b': 0.246, 'c': 0.426, 'd': 0.421, 'show': {'name': 'Cosmetic Surgery', 'presenter': 'Niall Crosby'},},
{'localTime': '8:45am', 'a': 0.893, 'b': 0.083, 'c': 0.532, 'd': 0.983, 'show': {'name': 'Cosmetic Surgery', 'presenter': 'Niall Crosby'},},
{
'localTime': '8:00am',
'show': {'name': 'Brickfield Park Sessions', 'presenter': 'Bricker McGee'},
'a': 0.231, 'b': 0.523, 'c': 0.423, 'd': 0.527,
},
{'localTime': '8:15am', 'a': 0.423, 'b': 0.452, 'c': 0.523, 'd': 0.543, 'show': {'name': 'Brickfield Park Sessions', 'presenter': 'Bricker McGee'},},
{'localTime': '8:30am', 'a': 0.537, 'b': 0.246, 'c': 0.426, 'd': 0.421, 'show': {'name': 'Brickfield Park Sessions', 'presenter': 'Bricker McGee'},},
{'localTime': '8:45am', 'a': 0.893, 'b': 0.083, 'c': 0.532, 'd': 0.983, 'show': {'name': 'Brickfield Park Sessions', 'presenter': 'Bricker McGee'},},
]
columnDefs = [
{'field': 'localTime'},
{
'field': 'show',
'cellRenderer': "RowSpanningComplexCellRenderer",
'rowSpan': {"function": "rowSpanningComplex(params, 'show')"},
'cellClassRules': {"show-cell": "params.value && params.data.rowSpanning"},
"width": 300
},
{'field': 'a'},
{'field': 'b'},
{'field': 'c'},
{'field': 'd'},
{'field': 'rowSpanning', 'hide': True}
]
app.layout = html.Div(
[
dag.AgGrid(
id="grid",
rowData=data,
columnDefs=columnDefs,
defaultColDef={"resizable": True, 'sortable': True, 'filter': True, 'flex': 1},
dashGridOptions={"suppressRowTransform": True},
),
],
)
app.clientside_callback(
"""async function () {
var api = await dash_ag_grid.getApiAsync("grid")
api.redrawRows();
return dash_clientside.no_update
}""",
Output("grid", "id"),
Input("grid", "virtualRowData"),
)
if __name__ == "__main__":
app.run(debug=True)
js file
var dagcomponentfuncs = (window.dashAgGridComponentFunctions = window.dashAgGridComponentFunctions || {});
dagfuncs.rowSpanningComplex = function (params, key) {
spanning = 0
var found;
var firstFound;
var included;
params.api.forEachNodeAfterFilterAndSort((node) => {
if (JSON.stringify(node.data[key]) == JSON.stringify(params.data[key]) || params.node.rowIndex == node.rowIndex) {
if (!found && found != 0 && !included) {
found = node.rowIndex
firstFound = node.rowIndex
if (found == params.node.rowIndex) {
included = true
}
spanning++
} else {
if ((node.rowIndex - found) == 1) {
found = node.rowIndex
if (found == params.node.rowIndex) {
included = true
}
spanning++
}
}
}
else if (!included) {
found = null
spanning = 0
}
})
params.node.setDataValue('rowSpanning', included ? (firstFound == params.node.rowIndex ? spanning || 1 : 0) : 1)
return included ? (firstFound == params.node.rowIndex ? spanning || 1 : 0) : 1;
}
var dagcomponentfuncs = (window.dashAgGridComponentFunctions = window.dashAgGridComponentFunctions || {});
dagcomponentfuncs.RowSpanningComplexCellRenderer = function (props) {
let children;
if (props.value && props.data.rowSpanning) {
children = [
React.createElement('div', {className: 'show-name'}, props.value.name),
React.createElement('div', {className: 'show-presenter'}, props.value.presenter),
]
}
return React.createElement('div', null, children)
}
css file
.show-cell {
background: #119dff;
border-left: 1px solid lightgrey !important;
border-right: 1px solid lightgrey !important;
border-bottom: 1px solid lightgrey !important;
}
.show-name {
font-weight: bold;
}
.show-presenter {
font-style: italic;
}