task guide
A grid in a Dash app
lattice_grid_dash.LatticeGrid puts the grid in a Dash layout, and every committed edit arrives at an ordinary callback as {colId, key, value}, the same shape a dropdown or a slider would send. One file, run below against the real package.
app.py
A small inventory grid: four SKUs, their warehouse, what is on hand and the reorder point. Editing
is turned on with options={"edit": True}, and the callback watches for a
change and recomputes which SKUs are now below their reorder point.
import pandas as pd
from dash import Dash, Input, Output, callback, html
import lattice_grid_dash
from lattice_grid_dash import dataframe_to_data, apply_cell_edit
df = pd.DataFrame({
"sku": ["BRK-100", "BRK-101", "BRK-102", "BRK-103"],
"warehouse": ["north", "north", "south", "south"],
"on_hand": [42, 15, 8, 120],
"reorder_at": [20, 20, 10, 50],
})
app = Dash(__name__)
app.layout = html.Div([
lattice_grid_dash.LatticeGrid(
id="grid",
data=dataframe_to_data(df),
options={"edit": True},
),
html.Pre(id="out"),
])
@callback(Output("out", "children"), Input("grid", "cellChanged"))
def on_edit(edit):
if not edit:
return "Edit on_hand for a SKU to see it here."
apply_cell_edit(df, edit) # keeps the server-side DataFrame in sync, typed
low = df[df["on_hand"] < df["reorder_at"]]["sku"].tolist()
return f"{edit['colId']} on {edit['key']} is now {edit['value']}. Below reorder point: {low}"
if __name__ == "__main__":
app.run(debug=False)
What the callback receives
Committing an edit in the grid sends cellChanged as
{"colId": ..., "key": ..., "value": ...}, one dictionary per edit.
apply_cell_edit(df, edit)
looks up the column and the row by that key, casts the value
to the column's dtype, and writes it into df in place, returning the same frame. Below,
the callback is called directly, exactly as Dash calls it after a grid edit, against the app above:
# Driving the callback exactly as Dash would after a grid edit event:
edit1 = {"colId": "on_hand", "key": "1", "value": 12}
print(on_edit(edit1))
edit2 = {"colId": "on_hand", "key": "2", "value": 3}
print(on_edit(edit2))
print(df)
on_hand on 1 is now 12. Below reorder point: ['BRK-101', 'BRK-102']
on_hand on 2 is now 3. Below reorder point: ['BRK-101', 'BRK-102']
sku warehouse on_hand reorder_at
0 BRK-100 north 42 20
1 BRK-101 north 12 20
2 BRK-102 south 8 10
3 BRK-103 south 120 50
on_hand
is still
int64
after both edits, and the reorder check, which
reads straight from the DataFrame's own dtypes, sees the change immediately because
apply_cell_edit
mutated the same frame the check runs against.
Run it
The grid's front-end code ships inside the package, so this runs with no build step and no request to a CDN at render time.
python app.py
Open the address Dash prints. Double-click an
on_hand
value, type a new number and
commit it: the text under the grid updates with the exact message above, computed against the
DataFrame the app is actually holding.
What next
For the same round trip in a notebook instead of an app, see a live grid in a notebook cell. For the datetime rule an edited timestamp column follows, see edit a DataFrame in the browser. Every prop and helper function is in the Python reference.