Apply ValueFormatter function to a row in AG Grid

I have the following function to format the text

f = {"function": "roundToTwoDecimals(params.value) + ' %'"}

I can apply this formatter to a AgGrid column with

"valueFormatter" : f

It is not clear to me how I could apply f to a row with specific properties, say every even numbered rows?

Hi @bonobo !

you can use JavaScript conditions in your function.
If you want a specific formatting on even rows, you can use params.node.rowIndex % 2 === 0

To see the values available through params use "valueFormatter": {"function": "log(params)"} and it will display params for "valueFormatter" in the browser’s console

Moreover, as the name of your function suggests, if you want to format the numbers in percentage with 2 decimals, you can easily use d3.format:

Here a simple example that formats even rows in percent with 2 decimals:

Code
import random

import dash_ag_grid as dag
from dash import Dash, html

app = Dash(__name__)

rowData = [
    {'Number': random.random()} for _ in range(10)
]

columnDefs = [
    {
        "field": "Number",
        "valueFormatter": {"function": "params.node.rowIndex % 2 === 0 ? d3.format('.2%')(params.value) : params.value"},
    },
]

app.layout = html.Div(
    [
        dag.AgGrid(
            columnDefs=columnDefs,
            rowData=rowData,
        ),
    ],
)

if __name__ == "__main__":
    app.run(debug=True)

image

2 Likes

Thanks Skiks, I understand, OK. It was as difficult as I thought once one knows about params.node.rowIndex. By the way, let me please ask one more question about the conditions. Is there way for the function to know whether the cell is in the last row? Or do I need to pass that as a variable to my JS function?

I think the easiest way is to use:

"valueFormatter": {"function": f"params.node.rowIndex === {len(rowData)-1} ? d3.format('.2%')(params.value) : params.value"}
1 Like

I’ve been challenged ! :crossed_swords:
@AnnMarieW challenge accepted !

what if there is sorting or filtering?

Indeed, valueFormatter is applied at initialisation, the formatting of each cell will stay the same even if they are sorted or filtered.

  1. First I found params.node.lastChild that will return true if if the row is the last of its row group, supposing you don’t use row groups, that will return true for the last row of the grid, even if filtered or sorted.
    Even if we don’t use filtering /sorting, I find the syntax better than f"params.node.rowIndex === {len(rowData)-1}"

  2. Then we have to reapply valueFormatter when filtering / sorting, which can be done using virtualRowData as trigger for a Dash callback that can reapply columnDefs to update the formating.

So finally we get:

Code
import random

import dash_ag_grid as dag
from dash import Dash, html, callback, Input, Output

app = Dash(__name__)

rowData = [
    {'Number': random.random()} for _ in range(8)
]

columnDefs = [
    {
        "field": "Number",
        "valueFormatter": {"function": f"params.node.lastChild ? d3.format('.2%')(params.value) : params.value"},
    },
]

app.layout = html.Div(
    [
        dag.AgGrid(
            id='my-grid',
            columnDefs=columnDefs,
            rowData=rowData,
            defaultColDef={"sortable": True, "filter": True},
        ),
    ],
)

@callback(
    Output("my-grid", "columnDefs"),
    Input("my-grid", "virtualRowData"),
    prevent_initial_call=True,
)
def update_value_formatter(_):
    return columnDefs

if __name__ == "__main__":
    app.run(debug=True)

And voilà! :tada:

3 Likes