A cell editor component is the UI that appears, normally inside a cell, that takes care of the edit operation.
An editor can be in a popup or in cell.
In Cell
The contents of the cell will be cleared and the editor will appear inside the cell. The editor will be constrained to the boundaries of the cell, so if it is larger than the provided area it will be clipped. When editing is finished, the editor will be removed and the renderer will be placed back inside the cell again.
Popup
The popup will appear over the cell, however it will not change the contents of the cell. Behind the popup the cell will remain intact until after editing is finished which will result in the cell being refreshed.
const columnDefs = [
{
field: 'name',
editable: True,
# uses the provided Text Cell Editor (which is the default)
cellEditor: 'agTextCellEditor'
},
# show this editor in a popup
cellEditorPopup: True,
# position the popup under the cell
cellEditorPopupPosition: 'under'
}
]
import dash_ag_grid as dag
from dash import Dash, html, dcc
app = Dash(__name__)
columnDefs = [
{
"headerName": "Make",
"field": "make",
"cellEditorPopup": True,
"cellEditorPopupPosition": "under",
},
{
"headerName": "Model",
"field": "model",
"cellEditorPopup": True,
"cellEditorPopupPosition": "over",
},
{"headerName": "Price", "field": "price"},
]
rowData = [
{"make": "Toyota", "model": "Celica", "price": 35000},
{"make": "Ford", "model": "Mondeo", "price": 32000},
{"make": "Porsche", "model": "Boxster", "price": 72000},
]
app.layout = html.Div(
[
dcc.Markdown(
"In this grid, the __Make__ column has a popup below the cell, the __Model__ has a popup above the cell, and the __Price__ has the default (in cell) editor."
),
dag.AgGrid(
id="cell-editors-basic-example",
columnDefs=columnDefs,
rowData=rowData,
columnSize="sizeToFit",
defaultColDef={"editable": True},
),
],
style={"margin": 20},
)
if __name__ == "__main__":
app.run(debug=False)
In this grid, the Make column has a popup below the cell, the Model has a popup above the cell, and the Price has the default (in cell) editor.
Parameters for cell editors can be dynamic to allow different selections based on what cell is being edited. For example, you might have a ‘City’ column that has values based on the ‘Country’ column. To do this, provide a function that returns parameters for the property cellEditorParams
.
This function is defined in the dashAgGridFunctions.js
file in the assets
folder:
var dagfuncs = window.dashAgGridFunctions = window.dashAgGridFunctions || {};
dagfuncs.dynamicOptions = function(params) {
const selectedCountry = params.data.country;
if (selectedCountry === 'United States') {
return {
values: ['Boston', 'Chicago', 'San Francisco'],
};
} else {
return {
values: ['Montreal', 'Vancouver', 'Calgary']
};
}
}
import dash_ag_grid as dag
from dash import Dash, html, dcc
app = Dash(__name__)
columnDefs = [
{
"field": "country",
"editable": False,
},
{
"headerName": "Select Editor",
"field": "city",
"cellEditor": "agSelectCellEditor",
"cellEditorParams": {"function": "dynamicOptions(params)"},
},
]
rowData = [
{"country": "United States", "city": "Boston"},
{"country": "Canada", "city": "Montreal"},
{"country": "Canada", "city": "Vancouver"},
]
app.layout = html.Div(
[
dcc.Markdown(
"This grid has dynamic options for city based on the country. Try editing the cities."
),
dag.AgGrid(
id="cell-editor-grid-2",
columnDefs=columnDefs,
rowData=rowData,
columnSize="sizeToFit",
defaultColDef={"editable": True},
),
],
style={"margin": 20},
)
if __name__ == "__main__":
app.run(debug=False)
This grid has dynamic options for city based on the country. Try editing the cities.
The example below demonstrates how to use a custom date picker as a cell editor. The ‘Date’ column uses a component
cell editor that allows you to pick a date using jQuery UI Datepicker.
DatePicker
is defined in the dashAgGridFunctions.js
file in the assets
folder.DatePicker
is supplied by name via cellEditor
.DatePicker
in the DatePicker
function.
import dash_ag_grid as dag
from dash import Dash, html, dcc
import pandas as pd
app = Dash(__name__, external_scripts=["https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.1/jquery.min.js", "https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"], external_stylesheets=["https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css"],)
df = pd.read_csv(
"https://raw.githubusercontent.com/plotly/datasets/master/ag-grid/olympic-winners.csv"
)
columnDefs = [
{"field": "date", "cellEditor": {"function": "DatePicker"}},
{"field": "athlete"},
{"field": "country"},
]
defaultColDef = {"flex": 1, "minWidth": 150, "editable": True}
app.layout = html.Div(
[
dcc.Markdown("Custom Date Picker Cell Editor Example"),
dag.AgGrid(
id="custom-date-picker-cell-editor-example",
columnDefs=columnDefs,
rowData=df.to_dict("records"),
defaultColDef=defaultColDef,
),
],
style={"margin": 20},
)
if __name__ == "__main__":
app.run(debug=True)
To run this example, add the following to your dashAgGridFunctions.js
file in your app’s assets folder:
var dagfuncs = window.dashAgGridFunctions = window.dashAgGridFunctions || {};
dagfuncs.DatePicker = class {
// gets called once before the renderer is used
init(params) {
// create the cell
this.eInput = document.createElement('input');
this.eInput.value = params.value;
this.eInput.classList.add('ag-input');
this.eInput.style.height = 'var(--ag-row-height)';
this.eInput.style.fontSize = 'calc(var(--ag-font-size) + 1px)';
// <a href="https://jqueryui.com/datepicker/">https://jqueryui.com/datepicker/</a>
$(this.eInput).datepicker({
dateFormat: 'dd/mm/yy',
onSelect: () => {
this.eInput.focus();
},
});
}
// gets called once when grid ready to insert the element
getGui() {
return this.eInput;
}
// focus and select can be done after the gui is attached
afterGuiAttached() {
this.eInput.focus();
this.eInput.select();
}
// returns the new value after editing
getValue() {
return this.eInput.value;
}
// any cleanup we need to be done here
destroy() {
// but this example is simple, no cleanup, we could
// even leave this method out as it's optional
}
// if true, then this editor will appear in a popup
isPopup() {
// and we could leave this method out also, false is the default
return false;
}
}
The example below demonstrates how to use a custom number input as a cell editor. The ‘Price’ column uses a component
cell editor that is an HTML input with type=”number”.
Notice the following:
NumberInput
is defined in the dashAgGridFunctions.js
file in the assets
folder.NumberInput
is supplied by name via cellEditor
.valueFormatter
. See import dash_ag_grid as dag
from dash import Dash, html
import pandas as pd
data = {
"item": ["A", "B", "C", "D"],
"price": [1154.99, 268.65, 100.00, 96.75],
}
df = pd.DataFrame(data)
columnDefs = [
{"field": "item"},
{
"field": "price",
"type": "rightAligned",
"valueFormatter": {"function": """d3.format("($,.2f")(params.value)"""},
"editable": True,
"cellEditor": {"function": "NumberInput"},
"cellEditorParams" : {"placeholder": "Enter a number"}
},
]
grid = dag.AgGrid(
id="custom-number-input-example-1",
columnDefs=columnDefs,
rowData=df.to_dict("records"),
)
app = Dash(__name__)
app.layout = html.Div(grid,style={"margin": 20})
if __name__ == "__main__":
app.run(debug=True)
To run this example, add the following to the dashAgGridFunctions.js
file in your app’s assets folder:
var dagfuncs = window.dashAgGridFunctions = window.dashAgGridFunctions || {};
dagfuncs.NumberInput = class {
// gets called once before the renderer is used
init(params) {
// create the cell
this.eInput = document.createElement('input');
this.eInput.value = params.value;
this.eInput.style.height = 'var(--ag-row-height)';
this.eInput.style.fontSize = 'calc(var(--ag-font-size) + 1px)';
this.eInput.style.borderWidth = 0;
this.eInput.style.width = '95%';
this.eInput.type = "number";
this.eInput.min = params.min;
this.eInput.max = params.max;
this.eInput.step = params.step || "any";
this.eInput.required = params.required;
this.eInput.placeholder = params.placeholder || "";
this.eInput.name = params.name;
this.eInput.disabled = params.disabled;
this.eInput.title = params.title || ""
}
// gets called once when grid ready to insert the element
getGui() {
return this.eInput;
}
// focus and select can be done after the gui is attached
afterGuiAttached() {
this.eInput.focus();
this.eInput.select();
}
// returns the new value after editing
getValue() {
return this.eInput.value;
}
// any cleanup we need to be done here
destroy() {
// but this example is simple, no cleanup, we could
// even leave this method out as it's optional
}
// if true, then this editor will appear in a popup
isPopup() {
// and we could leave this method out also, false is the default
return false;
}
}
Cell Editing can also be done with Cell Editor Components. See: