diff --git a/CHANGELOG.md b/CHANGELOG.md index 00e79d4..7687398 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ Links "DE#nnn" prior to version 2.0 point to the Dash Enterprise closed-source D - to maintain scroll position during a grid rerender, be sure to use `getRowId` - fixing side issue where `cellDoubleClicked` was forcing the grid to rerender +### Added + - [#330](https://github.com/plotly/dash-ag-grid/pull/330) Added `dash_clientside` to available functions for easier on-liner functions, esp. `eventListeners`. + - requested [#303](https://github.com/plotly/dash-ag-grid/issues/303) + ## [31.2.0] - 2024-02-25 diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index 57353de..0682fb9 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -79,6 +79,8 @@ const xssMessage = (context) => { const NO_CONVERT_PROPS = [...PASSTHRU_PROPS, ...PROPS_NOT_FOR_AG_GRID]; +const dash_clientside = window.dash_clientside || {}; + const agGridRefs = {}; apiGetters.getApi = (id) => agGridRefs[stringifyId(id)]?.api; @@ -1073,6 +1075,7 @@ export default class DashAgGrid extends Component { const parsedCondition = esprima.parse(funcString).body[0].expression; const context = { d3, + dash_clientside, ...customFunctions, ...window.dashAgGridFunctions, }; @@ -1083,6 +1086,7 @@ export default class DashAgGrid extends Component { const parsedCondition = esprima.parse(funcString).body[0].expression; const context = { d3, + dash_clientside, ...customFunctions, ...window.dashAgGridFunctions, setGridProps: this.props.setProps, diff --git a/tests/test_event_listeners.py b/tests/test_event_listeners.py new file mode 100644 index 0000000..5fbd289 --- /dev/null +++ b/tests/test_event_listeners.py @@ -0,0 +1,86 @@ +import dash_ag_grid as dag +from dash import Dash, html, dcc, Input, Output, State +import plotly.express as px +from . import utils +import json + +df = px.data.medals_wide() + +columnDefs = [] +for i in df.columns: + if i == "nation": + columnDefs.append({"field": i, "editable": False}) + else: + columnDefs.append({"field": i}) + + +def test_el001_event_listener(dash_duo): + app = Dash(__name__, suppress_callback_exceptions=True) + app.layout = html.Div( + [ + dag.AgGrid( + columnDefs=columnDefs, + rowData=df.to_dict("records"), + columnSize="sizeToFit", + defaultColDef={"editable": True}, + id="grid", + getRowId="params.data.nation", + eventListeners={'cellContextMenu': ['showOutput(params, setGridProps)']}, + dashGridOptions={'suppressContextMenu': True, "preventDefaultOnContextMenu": True} + ), + html.Div(id="log") + ] + ) + + app.clientside_callback( + """function countEvents(cellClicked) { + return JSON.stringify(cellClicked) + }""", + Output("log", "children"), + Input("grid", "cellClicked"), + prevent_initial_call=True, + suppress_callback_exception=True + ) + + dash_duo.start_server(app) + + grid = utils.Grid(dash_duo, "grid") + grid.wait_for_cell_text(0, 0, "South Korea") + + # Test left click. + grid.get_cell(1, 2).click() + cellClicked = dash_duo.find_element('#log').text + assert json.loads(cellClicked).get('value') == 15 + + # Test right click + action = utils.ActionChains(dash_duo.driver) + action.context_click(grid.get_cell(0, 2)).perform() + cellClicked = dash_duo.find_element('#log').text + assert json.loads(cellClicked).get('value') == 13 + assert json.loads(cellClicked).get('contextMenu') + +def test_el002_event_listener(dash_duo): + app = Dash(__name__, suppress_callback_exceptions=True) + app.layout = html.Div( + [ + dag.AgGrid( + columnDefs=columnDefs, + rowData=df.to_dict("records"), + columnSize="sizeToFit", + defaultColDef={"editable": True}, + id="grid", + getRowId="params.data.nation", + eventListeners={'cellClicked': ['dash_clientside.set_props("log", {children: "rawr"})']}, + ), + html.Div(id="log") + ] + ) + + dash_duo.start_server(app) + + grid = utils.Grid(dash_duo, "grid") + grid.wait_for_cell_text(0, 0, "South Korea") + + # Test left click. + grid.get_cell(1, 2).click() + assert dash_duo.find_element('#log').text == "rawr"