Column Pinning

When you pin columns, the grid reorders columns putting those pinned "left" first, and those pinned "right" last.

Pin Columns

To pin a column it is possible to:

The following example shows how to pin columns using Column Definition at initialization and using Callbacks to update
the pinned parameter through Column State.

It is also possible to choose to clear or keep the current pinned columns when the pinned state is updated through the
callback using the two firsts buttons.

Note how pinned columns remain visible as you scroll through other columns.

import dash_ag_grid as dag
from dash import Dash, html, dcc, Input, Output, State, ctx, callback
from plotly import data

app = Dash(__name__)

df = data.election()

columnDefs = [
    {"field": "district"},
    {"field": "Coderre"},
    {"field": "Bergeron"},
    {"field": "Joly"},
    {"field": "total", "pinned": "right"},
    {"field": "winner", "pinned": "left"},
]

app.layout = html.Div(
    [
        "Current Pinned Columns:",
        dcc.RadioItems(
            id='radio-column-pinning-option',
            options=[
                {'label': 'Clear', 'value': True},
                {'label': 'Keep', 'value': False}
            ],
            value=True, inline=True,
        ),
        html.Button("District Left", id="btn-column-pinning-left"),
        html.Button("Winner Left + Total Right", id="btn-column-pinning-left-right"),
        html.Button("Clear All", id="btn-column-pinning-clear"),
        dag.AgGrid(
            id="column-pinning-simple-example",
            rowData=df.to_dict("records"),
            columnDefs=columnDefs,
            defaultColDef={"resizable": True, "sortable": True, "filter": True},
        ),
    ],
)


@callback(
    Output("column-pinning-simple-example", "columnState"),
    State("column-pinning-simple-example", "columnState"),
    State("radio-column-pinning-option", "value"),
    Input("btn-column-pinning-left", "n_clicks"),
    Input("btn-column-pinning-left-right", "n_clicks"),
    Input("btn-column-pinning-clear", "n_clicks"),
    prevent_initial_call=True,
)
def update_pinned_state(col_state, clear, *_):
    if ctx.triggered_id == "btn-column-pinning-clear":
        return [{'colId': col['colId'], 'pinned': False} for col in col_state]

    if ctx.triggered_id == "btn-column-pinning-left":
        new_pinned = {'district': 'left'}
    elif ctx.triggered_id == "btn-column-pinning-left-right":
        new_pinned = {'winner': 'left', 'total': 'right'}

    return [
        {
            'colId': col['colId'],
            'pinned': new_pinned.get(
                col['colId'], False if clear else col['pinned']
            ),
        }
        for col in col_state
    ]


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

Lock Pinning

You can prevent a user from modifying the pinning state of a column by setting lockPinned to True on its column
definition.

The following example shows the behavior of lock-pinned columns. Note the following:

View the CSS classes used for this example

These CSS classes must be added to any *.css file in the assets folder.
See Loading CSS files for more information.

span.legend-box {
    display: inline-block;
    border: 1px solid #aaa;
    height: 15px;
    width: 15px;
    margin-left: 15px;
    margin-right: 5px;
}

.lock-pinned {
    background: #119dff;
}

.lock-unpinned {
    background: #66c2a5;
}
import dash_ag_grid as dag
from dash import Dash, html
from plotly import data

app = Dash(__name__)

df = data.election()

columnDefs = [
    {"field": "winner", "pinned": "left", "lockPinned": True, "cellClass": "lock-pinned"},
    {"field": "district", "lockPinned": True, "cellClass": "lock-unpinned"},
    {"field": "Coderre"},
    {"field": "Bergeron"},
    {"field": "Joly"},
    {"field": "total", "pinned": "right"},
]

app.layout = html.Div(
    [
        html.Div([
            html.Span(className="legend-box lock-pinned"), "Lock-Pinned Column - Pinned",
            html.Span(className="legend-box lock-unpinned"), "Lock-Pinned Column - not Pinned",
        ]),
        dag.AgGrid(
            id="column-pinning-lock-pinning",
            columnDefs=columnDefs,
            rowData=df.to_dict("records"),
            columnSize="sizeToFit",
            defaultColDef={"resizable": True, "sortable": True, "filter": True, },
        ),
    ],
)

if __name__ == "__main__":
    app.run(debug=True)
Lock-Pinned Column - Pinned Lock-Pinned Column - not Pinned