Does anyone know how to style a ag-grid table in Dash row wise? I currently use a jupyter notebook and ipyaggrid.Grid to generate a ag-grid based datatable. When defining columnDefs for my Grid object, I could pass a Javascript function as a string to the cellRenderer key (like shown in the code below).
I tried to move the same table to a plotly dash app using the open source AgGrid component from dash_ag_grid. When running the app I get following error in the browser console when passing same javascript string to columnDef’s cellRenderer in AgGrid:
AG Grid: Looking for component [
function (params){…
…] but it wasn’t found. Have you registered the component?
Does someone know how to pass a function to the cellRenderer or how to style ag-grid tables in general in Dash row wise?
# define javascript function to style column "Item"
cell_renderer_items = '''
function (params){
let v = params.value;
// header (bold)
if (['Sales','Gross Profit','EBITDA','Operating Profit (EBIT)','Net Operating Profit After Tax (NOPAT)',
'FCF Yield (%)','ROE', 'ROIC unadjusted','ROIC adjusted', 'EVA (ROIC unadjusted - WACC)',
'EVA (ROIC adjusted - WACC)','EV/IC','P/B'].indexOf(params.node.data.Item) >= 0) {
return `<div style = 'text-align:left'><b>${v}</b></div>`;
}
// sub-item important (bold, italic & margin-left)
else if (['Gross Margin (%)','EBITDA Margin (%)','EBIT Margin (OPM) (%)',
'NOPAT Margin (%)'].indexOf(params.node.data.Item) >= 0) {
return `<div style = 'text-align:left'><span style='margin-left: 1rem'><b><i>${v}</i></b></span></div>`;
}
// sub-item (normal -> margin-left)
else if (['Current Rental Expense','Rental Expense Year 1','Rental Expense Year 2','Rental Expense Year 3',
'Rental Expense Year 4','Rental Expense Year 5','Rental Expense Beyond Year 5',
'Total IC adjusted','NOPAT adjusted'].indexOf(params.node.data.Item) >= 0) {
return `<div'><span style='margin-left: 1rem'>${v}</span></div>`;
}
// sub-item (italic -> margin-left)
else if (['YoY Sales Growth (%)','YoY COGS Growth (%)','YoY SG&A Growth (%)','YoY D&A Growth (%)',
'YoY OPM Growth (bps)','YoY NOPAT Margin Growth (bps)','Goodwill to EV (%)','Capex to Sales (%)',
'Capex to Depreciation (%)','FCF Margin (%)','Equity','NOPAT','Invested Capital (IC)'].indexOf(params.node.data.Item) >= 0) {
return `<div'><span style='margin-left: 1rem'><i>${v}</i></span></div>`;
}
// sub-item (italic -> margin-left)
else if (['Net Income','Interest Expense on Debt','Nonoperating Income (Net)'].indexOf(params.node.data.Item) >= 0) {
return `<div'><span style='margin-left: 2rem'><i>${v}</i></span></div>`;
}
// main header (grey background, text color white, bold)
else if (['Profit & Loss','Balance Sheet','Cash Flow','DuPont Analysis','Profitability','Key Multiples'].indexOf(params.node.data.Item) >= 0) {
return `<div style = 'text-align:center'><span style='color: white'><b>${v}</b></span></div>`;
}
// header (normal)
else {
return v;
}
}
'''
# define javascript function to allow row based cell editing
cell_editable_func = '''
function (params){
if (['Profit & Loss','Balance Sheet','Cash Flow','DuPont Analysis','Profitability','Key Multiples',
'YoY Sales Growth (%)','YoY COGS Growth (%)',
'Gross Profit','Gross Margin (%)','YoY SG&A Growth (%)','EBITDA Margin (%)','YoY D&A Growth (%)','EBIT Margin (OPM) (%)',
'YoY OPM Growth (bps)','Net Operating Profit After Tax (NOPAT)','NOPAT Margin (%)','YoY NOPAT Margin Growth (bps)',
'Goodwill to EV (%)','Capex to Sales (%)','Capex to Depreciation (%)','Net Debt/EBITDA','ROE','Total Equity',
'Net Pension Liabilities to EV (%)','FCF','FCF Margin (%)','Cash conversion (FCF/EBITDA)','Cash conversion (CFO/EBITDA)',
'Operating Profit Margin (OPM)','ROIC unadjusted','NOPAT','Invested Capital (IC)','PV Future Lease Obligations',
'Total IC adjusted','NOPAT adjusted','ROIC adjusted','EVA (ROIC unadjusted - WACC)','EVA (ROIC adjusted - WACC)','EV/IC',
'EV/Sales (T12M)','EV/EBITDA (T12M)','P/S','P/E','EPS (Growth)'].indexOf(params.node.data.Item) >= 0)
{
return false;
}
else{
return true;
}
}
'''
column_defs = [
{'field': 'Item', 'type': 'textColumn', 'editable': False, 'pinned': 'left','lockPinned': True,
'width':280,'suppressSizeToFit': True, 'cellRenderer': cell_renderer_items}]
for col in df.columns:
if col != 'Item':
column_defs.append({'field': col, 'type': 'numberColumn', 'suppressMovable': True, 'editable': cell_editable_func})
Grid(
grid_data = df.reset_index()
,grid_options = {'columnDefs':column_defs}
)
The resulting grid looks like this: