diff --git a/src/lib/components/AgGrid.react.js b/src/lib/components/AgGrid.react.js index 5813dd3b..52c55cac 100644 --- a/src/lib/components/AgGrid.react.js +++ b/src/lib/components/AgGrid.react.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import LazyLoader from '../LazyLoader'; import React, {lazy, Suspense, useState, useCallback, useEffect} from 'react'; +import {pick} from 'ramda'; const RealAgGrid = lazy(LazyLoader.agGrid); const RealAgGridEnterprise = lazy(LazyLoader.agGridEnterprise); @@ -9,6 +10,25 @@ function getGrid(enable) { return enable ? RealAgGridEnterprise : RealAgGrid; } +export const defaultProps = { + className: 'ag-theme-alpine', + resetColumnState: false, + exportDataAsCsv: false, + selectAll: false, + deselectAll: false, + enableEnterpriseModules: false, + updateColumnState: false, + persisted_props: ['selectedRows'], + persistence_type: 'local', + suppressDragLeaveHidesColumns: true, + dangerously_allow_code: false, + rowModelType: 'clientSide', + dashGridOptions: {}, + filterModel: {}, + paginationGoTo: null, + selectedRows: [], +}; + /** * Dash interface to AG Grid, a powerful tabular data component. */ @@ -45,31 +65,26 @@ function DashAgGrid(props) { return ( - + ); } +const REACT_VERSION_DASH2_COMPAT = 18.3; +if ( + parseFloat(React.version.substring(0, React.version.lastIndexOf('.'))) < + REACT_VERSION_DASH2_COMPAT +) { + DashAgGrid.defaultProps = defaultProps; +} else { + DashAgGrid.dashPersistence = pick( + ['persisted_props', 'persistence_type'], + defaultProps + ); +} + DashAgGrid.dashRenderType = true; -DashAgGrid.defaultProps = { - className: 'ag-theme-alpine', - resetColumnState: false, - exportDataAsCsv: false, - selectAll: false, - deselectAll: false, - enableEnterpriseModules: false, - updateColumnState: false, - persisted_props: ['selectedRows'], - persistence_type: 'local', - suppressDragLeaveHidesColumns: true, - dangerously_allow_code: false, - rowModelType: 'clientSide', - dashGridOptions: {}, - filterModel: {}, - paginationGoTo: null, - selectedRows: [], -}; DashAgGrid.propTypes = { /******************************** * DASH PROPS @@ -751,7 +766,6 @@ DashAgGrid.propTypes = { }; export const propTypes = DashAgGrid.propTypes; -export const defaultProps = DashAgGrid.defaultProps; export default DashAgGrid; diff --git a/src/lib/fragments/AgGrid.react.js b/src/lib/fragments/AgGrid.react.js index 7250339f..12f0b956 100644 --- a/src/lib/fragments/AgGrid.react.js +++ b/src/lib/fragments/AgGrid.react.js @@ -15,11 +15,7 @@ import { assoc, assocPath, } from 'ramda'; -import { - propTypes as _propTypes, - defaultProps as _defaultProps, - apiGetters, -} from '../components/AgGrid.react'; +import {propTypes as _propTypes, apiGetters} from '../components/AgGrid.react'; import { COLUMN_DANGEROUS_FUNCTIONS, COLUMN_MAYBE_FUNCTIONS, @@ -1342,10 +1338,10 @@ export function DashAgGrid(props) { // Handle gridApi initialization - column state application useEffect(() => { - if (gridApi && gridApi !== prevGridApi && props.columnState) { + if (gridApi && gridApi !== prevGridApi && columnState_push) { setColumnState(); } - }, [gridApi, prevGridApi, props.columnState, setColumnState]); + }, [gridApi, prevGridApi, columnState_push]); // Handle gridApi initialization - finalization useEffect(() => { @@ -1378,7 +1374,7 @@ export function DashAgGrid(props) { setColumnState_push(true); } } - }, [props.columnState, props.loading_state, columnState_push]); + }, [props.columnState, props.loading_state]); // Handle ID changes useEffect(() => { @@ -1605,11 +1601,9 @@ export function DashAgGrid(props) { ); } -DashAgGrid.defaultProps = _defaultProps; DashAgGrid.propTypes = {parentState: PropTypes.any, ..._propTypes}; export const propTypes = DashAgGrid.propTypes; -export const defaultProps = DashAgGrid.defaultProps; var dagfuncs = (window.dash_ag_grid = window.dash_ag_grid || {}); dagfuncs.useGridFilter = useGridFilter; diff --git a/src/lib/utils/propCategories.js b/src/lib/utils/propCategories.js index a2f8cf06..253fe6d3 100644 --- a/src/lib/utils/propCategories.js +++ b/src/lib/utils/propCategories.js @@ -321,6 +321,8 @@ export const PASSTHRU_PROPS = ['rowData']; */ export const PROPS_NOT_FOR_AG_GRID = [ 'children', + 'dashRenderType', + 'licenseKey', 'setProps', 'loading_state', 'enableEnterpriseModules', @@ -354,6 +356,7 @@ export const PROPS_NOT_FOR_AG_GRID = [ 'scrollTo', 'eventListeners', 'eventData', + 'paginationInfo', ]; /** diff --git a/tests/test_column_state.py b/tests/test_column_state.py index 5b573b0b..2b5b45cc 100644 --- a/tests/test_column_state.py +++ b/tests/test_column_state.py @@ -1,4 +1,4 @@ -from dash import Dash, html, Output, Input, no_update, State, ctx +from dash import Dash, html, Output, Input, no_update, State, ctx, Patch import dash_ag_grid as dag import plotly.express as px import json @@ -84,7 +84,7 @@ alt_colState = [ { "colId": "price", - "width": 198, + "width": 200, "hide": False, "pinned": None, "sort": "asc", @@ -239,7 +239,7 @@ def loadState(n): dash_duo.find_element("#get-column-state-button").click() testState = colState.copy() - testState[1]["width"] = 198 + testState[1]["width"] = 200 until( lambda: json.dumps(testState) in dash_duo.find_element("#reset-column-state-grid-pre").text, @@ -315,4 +315,206 @@ def make_grid(n): for x in range(10): dash_duo.find_element("#add-grid").click() time.sleep(2) # pausing to emulate separation because user inputs - assert list(filter(lambda i: i.get("level") != "WARNING", dash_duo.get_logs())) == [] \ No newline at end of file + assert list(filter(lambda i: i.get("level") != "WARNING", dash_duo.get_logs())) == [] + +def test_cs003_column_state(dash_duo): + data = [ + { + "localTime": "5:00am", + "a": 0.231, + "b": 0.523, + "c": 0.423, + "d": 0.527, + }, + { + "localTime": "5:15am", + "a": 0.423, + "b": 0.452, + "c": 0.523, + "d": 0.543, + }, + { + "localTime": "5:30am", + "a": 0.537, + "b": 0.246, + "c": 0.426, + "d": 0.421, + }, + { + "localTime": "5:45am", + "a": 0.893, + "b": 0.083, + "c": 0.532, + "d": 0.983, + }, + { + "localTime": "6:00am", + "a": 0.231, + "b": 0.523, + "c": 0.423, + "d": 0.527, + }, + { + "localTime": "6:15am", + "a": 0.423, + "b": 0.452, + "c": 0.523, + "d": 0.543, + }, + { + "localTime": "6:30am", + "a": 0.537, + "b": 0.246, + "c": 0.426, + "d": 0.421, + }, + { + "localTime": "6:45am", + "a": 0.893, + "b": 0.083, + "c": 0.532, + "d": 0.983, + }, + { + "localTime": "7:00am", + "a": 0.231, + "b": 0.523, + "c": 0.423, + "d": 0.527, + }, + { + "localTime": "7:15am", + "a": 0.423, + "b": 0.452, + "c": 0.523, + "d": 0.543, + }, + { + "localTime": "7:30am", + "a": 0.537, + "b": 0.246, + "c": 0.426, + "d": 0.421, + }, + { + "localTime": "7:45am", + "a": 0.893, + "b": 0.083, + "c": 0.532, + "d": 0.983, + }, + { + "localTime": "8:00am", + "a": 0.231, + "b": 0.523, + "c": 0.423, + "d": 0.527, + }, + { + "localTime": "8:15am", + "a": 0.423, + "b": 0.452, + "c": 0.523, + "d": 0.543, + }, + { + "localTime": "8:30am", + "a": 0.537, + "b": 0.246, + "c": 0.426, + "d": 0.421, + }, + { + "localTime": "8:45am", + "a": 0.893, + "b": 0.083, + "c": 0.532, + "d": 0.983, + }, + { + "localTime": "8:00am", + "a": 0.231, + "b": 0.523, + "c": 0.423, + "d": 0.527, + }, + { + "localTime": "8:15am", + "a": 0.423, + "b": 0.452, + "c": 0.523, + "d": 0.543, + }, + { + "localTime": "8:30am", + "a": 0.537, + "b": 0.246, + "c": 0.426, + "d": 0.421, + }, + { + "localTime": "8:45am", + "a": 0.893, + "b": 0.083, + "c": 0.532, + "d": 0.983, + }, + ] + + columnDefs = [ + {"field": "localTime"}, + {"field": "a"}, + {"field": "b"}, + {"field": "c"}, + {"field": "d"}, + ] + + app = Dash(__name__) + + app.layout = html.Div( + [ + html.Div( + [ + html.Button("Remove Column", id="remove-column", n_clicks=0), + html.Div( + id="grid-holder", + children=[ + dag.AgGrid( + id=f"grid", + columnDefs=columnDefs, + rowData=data, + columnSize="autoSize", + ) + ], + ), + ], + ), + ] + ) + + @app.callback( + Output("grid", "columnDefs"), + Input("remove-column", "n_clicks"), + ) + def remove_column(n): + if n: + cols = Patch() + if n < 3: + del cols[0] + return cols + return no_update + + dash_duo.start_server( + app, + debug=True, + use_reloader=False, + use_debugger=True, + dev_tools_hot_reload=False, + dev_tools_props_check=True, + dev_tools_disable_version_check=True, + ) + + for x in range(3): + dash_duo.find_element("#remove-column").click() + time.sleep(2) # pausing to emulate separation because user inputs + assert list(filter(lambda i: i.get("level") != "ERROR", dash_duo.get_logs())) == []