Skip to content

Commit df75c87

Browse files
authored
Merge pull request #2619 from plotly/table-escape-col-ids
Fix #2615 - allow special characters in dash-table column IDs
2 parents eaab7f2 + 3391ee9 commit df75c87

File tree

4 files changed

+40
-12
lines changed

4 files changed

+40
-12
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
77

88
## Fixed
99

10-
- [#2616](https://github.com/plotly/dash/pull/2616) Add mapping of tsconfig compiler option `moduleResolution`, fixes [#2618](https://github.com/plotly/dash/issues/2618)
10+
- [#2619](https://github.com/plotly/dash/pull/2619) Fix for dash-table column IDs containing special characters
11+
- [#2616](https://github.com/plotly/dash/pull/2616) Add mapping of tsconfig compiler option `moduleResolution`, fixes [#2618](https://github.com/plotly/dash/issues/2618)
1112
- [#2596](https://github.com/plotly/dash/pull/2596) Fix react-dom throwing unique key prop error for markdown table, fix [#1433](https://github.com/plotly/dash/issues/1433)
1213
- [#2589](https://github.com/plotly/dash/pull/2589) CSS for input elements not scoped to Dash application
1314
- [#2599](https://github.com/plotly/dash/pull/2599) Fix background callback cancel inputs used in multiple callbacks and mixed cancel inputs across pages.

components/dash-table/src/dash-table/components/ControlledTable/index.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ const INNER_STYLE = {
5555
minWidth: '100%'
5656
};
5757

58+
const columnSelector = (column_id: string) =>
59+
`[data-dash-column="${CSS.escape(column_id)}"]:not(.phantom-cell)`;
60+
5861
export default class ControlledTable extends PureComponent<ControlledTableProps> {
5962
private readonly menuRef = React.createRef<HTMLDivElement>();
6063
private readonly stylesheet: Stylesheet = new Stylesheet(
@@ -176,8 +179,9 @@ export default class ControlledTable extends PureComponent<ControlledTableProps>
176179
(active.column_id !== active_cell?.column_id ||
177180
active.row !== active_cell?.row)
178181
) {
182+
const {column_id, row} = active_cell;
179183
const target = this.$el.querySelector(
180-
`td[data-dash-row="${active_cell.row}"][data-dash-column="${active_cell.column_id}"]:not(.phantom-cell)`
184+
`td[data-dash-row="${row}"]${columnSelector(column_id)}`
181185
) as HTMLElement;
182186
if (target) {
183187
target.focus();
@@ -1166,15 +1170,11 @@ export default class ControlledTable extends PureComponent<ControlledTableProps>
11661170
const {table, tooltip: t} = this.refs as {[key: string]: any};
11671171

11681172
if (t) {
1169-
const cell = header
1170-
? table.querySelector(
1171-
`tr:nth-of-type(${
1172-
row + 1
1173-
}) th[data-dash-column="${id}"]:not(.phantom-cell)`
1174-
)
1175-
: table.querySelector(
1176-
`td[data-dash-column="${id}"][data-dash-row="${row}"]:not(.phantom-cell)`
1177-
);
1173+
const cell = table.querySelector(
1174+
header
1175+
? `tr:nth-of-type(${row + 1}) th${columnSelector(id)}`
1176+
: `td[data-dash-row="${row}"]${columnSelector(id)}`
1177+
);
11781178

11791179
(this.refs.tooltip as TableTooltip).updateBounds(cell);
11801180
}

components/dash-table/tests/selenium/test_column.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,30 @@ def test_colm008_top_row_by_subset(test):
267267
for r in range(3):
268268
if target.column(c).exists(r):
269269
assert target.column(c).is_selected(r)
270+
271+
272+
def test_colm009_newline_id(test):
273+
app = dash.Dash(__name__)
274+
275+
columns = [
276+
{"name": "aaabbb", "id": "aaa\nbbb"},
277+
{"name": "cccddd", "id": "ccc\nddd"},
278+
]
279+
data = [{columns[c]["id"]: r + (3 * c) + 1 for c in [0, 1]} for r in [0, 1, 2]]
280+
tooltip_data = [{k: str(v * 11) for k, v in row.items()} for row in data]
281+
282+
app.layout = DataTable(
283+
id="table", columns=columns, data=data, tooltip_data=tooltip_data
284+
)
285+
286+
test.start_server(app)
287+
288+
target = test.table("table")
289+
cell = target.cell(1, 1)
290+
291+
target.is_ready()
292+
cell.move_to()
293+
# note first I tried tooltip.exists() and tooltip.get_text() like in ttip001
294+
# but that didn't work? didn't wait for it perhaps?
295+
test.wait_for_text_to_equal(".dash-tooltip", "55")
296+
assert test.get_log_errors() == []

dash/_jupyter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ def wait_for_app():
403403
@staticmethod
404404
def _display_in_colab(dashboard_url, port, mode, width, height):
405405
# noinspection PyUnresolvedReferences
406-
from google.colab import output # pylint: disable=E0401,C0415
406+
from google.colab import output # pylint: disable=E0401,E0611,C0415
407407

408408
if mode == "inline":
409409
output.serve_kernel_port_as_iframe(port, width=width, height=height)

0 commit comments

Comments
 (0)