Skip to content
This repository was archived by the owner on Jun 4, 2024. It is now read-only.

Commit 1f6d4b4

Browse files
Refactor table API (#446)
1 parent 6d49d2d commit 1f6d4b4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+1425
-1526
lines changed

CHANGELOG.md

+80-6
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,90 @@ All notable changes to this project will be documented in this file.
33
This project adheres to [Semantic Versioning](http://semver.org/).
44

55
## [Unreleased]
6+
### Changed
7+
[#446](https://github.com/plotly/dash-table/pull/446)
8+
- Table API rework
9+
#### NEW
10+
- `column.sort_as_null`: Allows sorting behavior customization.
11+
Accepts an array of string, number or booleans.
12+
13+
#### REMOVED
14+
- `column.clearable`: Allows clearing the value of a dropdown cell.
15+
Removed in favor of `dropdown_**` `clearable` nested property.
16+
- `column.options`
17+
Removed. Redundant with `dropdown`.
18+
- `pagination_settings`
19+
Replaced by two props `page_current` and `page_size`.
20+
21+
#### RENAMED
22+
- `column_static_tooltip`
23+
Renamed to `tooltip`.
24+
- `column_conditional_tooltips`
25+
Renamed to `tooltip_conditional`.
26+
- `filter`
27+
Renamed to `filter_query`.
28+
- `sort_type`
29+
Renamed to `sort_mode`.
30+
- `derived_filter_structure`
31+
Renamed to `derived_filter_query_structure`.
32+
33+
#### MODIFIED
34+
- `column.deletable`: Allows column deletion.
35+
Now accepts a boolean or an array of booleans (for multi-line headers).
36+
For example, if there are multiple headers and you want the second header row to be deletable, this would be `[False, True]`.
37+
- `column.editable_name`: Allows column renaming.
38+
Renamed to `column.renamable`
39+
Now accepts a boolean or an array of booleans (for multi-line headers).
40+
For example, if there are multiple headers and you want the second row's header's name to be editable, this would be `[False, True]`.
41+
- `column.id`
42+
Now accepts `string` only -- `number` column ids can be casted to string.
43+
- `n_fixed_columns`: Will fix columns to the left.
44+
Renamed to `fixed_columns`
45+
Now accepts an object { headers: boolean, data: number } instead of a number.
46+
{ headers: true } determines the number of columns to fix automatically. For example, if the rows are selectable or deletable, { headers: true } would fix those columns automatically. If { headers: true, data: 2 }, it would fix the first two data columns in addition to the selectable and deletable if visible.
47+
- `n_fixed_rows`: Will fix rows to the top.
48+
Renamed to `fixed_rows`
49+
Now accepts an object { headers: boolean, data: number } instead of a number.
50+
{ headers: true } determines the number of rows to fix automatically (i.e. if there are multiple headers, it will fix all of them as well as the filter row).
51+
{ headers: true, data: 2} would fix all of the header rows as well as the first 2 data rows.
52+
- `pagination_mode`
53+
Renamed to `page_action`.
54+
`'fe'` is now `'native'`, `'be'` is now `'custom'`, and `false` is now '`none'`
55+
- `column_static_dropdown`
56+
Renamed to `dropdown`.
57+
Now an object with each entry refering to a Column ID. Each nested prop expects.
58+
`clearable` and `options`.
59+
- `column_conditional_dropdowns`
60+
Renamed to `dropdown_conditional`.
61+
`condition` changed to the same `if` nested prop used by styles.
62+
`dropdown` renamed to `options`.
63+
- `dropdown_properties`
64+
Renamed to `dropdown_data`.
65+
Matches the `data` structure.
66+
- `tooltips`
67+
Renamed to `tooltip_data`.
68+
Matches the `data` structure.
69+
- `filtering`
70+
Renamed to `filter_action`.
71+
- `sorting`
72+
Renamed to `sort_action`.
73+
- `sorting_treat_empty_string_as_none`
74+
Renamed to `sort_as_null`.
75+
Now accepts an array of string, number or booleans that can be ignored during sort.
76+
Table-level prop for the `column.sort_as_null` column nested prop.
77+
- `style_data_conditional`
78+
Renamed `filter` to `filter_query`.
79+
680
### Added
781
[#456](https://github.com/plotly/dash-table/issues/456)
882
- Support for dash-table is now available for R users of Dash.
983

1084
### Fixed
1185
[#434](https://github.com/plotly/dash-table/issues/434)
12-
- Fix CSS borders propeties overwrite style_* borders properties.
86+
- Fix CSS borders properties overwrite style_* borders properties.
1387

1488
[#435](https://github.com/plotly/dash-table/issues/435)
15-
- selected_cells background color is set through styling pipeline / derivations.
89+
- selected_cells background color is set through styling pipeline / derivations.
1690

1791
## [3.7.0] - 2019-05-15
1892
### Added
@@ -315,8 +389,8 @@ The remote URL path for the bundle was incorrect.
315389
}
316390

317391
A+B = {
318-
background_color: 'floralwhite', // from A, not overriden
319-
color: 'black', // from B, A overriden
392+
background_color: 'floralwhite', // from A, not overridden
393+
color: 'black', // from B, A overridden
320394
font_size: 22, // from B
321395
font_type: 'monospace', // from A
322396
width: 100 // from A
@@ -352,7 +426,7 @@ The remote URL path for the bundle was incorrect.
352426
if: { column_id: string | number, header_index: number | 'odd' | 'even' },
353427
...CSSProperties
354428
}]
355-
- All CSSProperties are supported in kebab-cass, camelCase and snake_case
429+
- All CSSProperties are supported in kebab-case, camelCase and snake_case
356430

357431
### Changed
358432
- Renaming 'dataframe' props to 'data'
@@ -637,7 +711,7 @@ Freeze Top Rows (Limitations)
637711
Freeze Left Columns (Limitations)
638712
- performance is highly impacted if the table is in a scrollable container as the frozen columns position has to be recalculated on each scroll event; impact is minimal up to 50-100 items and makes the table difficult to use with 250-500 items
639713
- can't freeze rows and columns at the same time
640-
- when using merged headers, make sure that the number of fixed columns respects the merged headers, otherwise there will be some unresolved visual bugs/artefacts
714+
- when using merged headers, make sure that the number of fixed columns respects the merged headers, otherwise there will be some unresolved visual bugs/artifacts
641715
- rows are assumed to all have the same height
642716

643717
Deletable Columns (Limitations)

demo/App.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class App extends Component {
4040
className='clear-filters'
4141
onClick={() => {
4242
const tableProps = R.clone(this.state.tableProps);
43-
tableProps.filter = '';
43+
tableProps.filter_query = '';
4444

4545
this.setState({ tableProps });
4646
}}
@@ -53,7 +53,7 @@ class App extends Component {
5353
}
5454
onBlur={e => {
5555
const tableProps = R.clone(this.state.tableProps);
56-
tableProps.filter = e.target.value;
56+
tableProps.filter_query = e.target.value;
5757

5858
this.setState({ tableProps });
5959
}} />

demo/AppMode.ts

+36-41
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ import Environment from 'core/environment';
44

55
import { generateMockData, IDataMock, generateSpaceMockData } from './data';
66
import {
7-
ContentStyle,
87
PropsWithDefaults,
98
ChangeAction,
109
ChangeFailure,
1110
IVisibleColumn,
12-
ColumnType
11+
ColumnType,
12+
TableAction
1313
} from 'dash-table/components/Table/props';
1414
import { TooltipSyntax } from 'dash-table/tooltips/props';
1515

@@ -46,19 +46,19 @@ function getBaseTableProps(mock: IDataMock) {
4646
on_change: {
4747
action: ChangeAction.None
4848
},
49-
editable_name: true,
49+
renamable: true,
5050
deletable: true
5151
})),
52-
column_static_dropdown: [
53-
{
54-
id: 'bbb',
55-
dropdown: ['Humid', 'Wet', 'Snowy', 'Tropical Beaches'].map(i => ({
52+
dropdown: {
53+
bbb: {
54+
clearable: true,
55+
options: ['Humid', 'Wet', 'Snowy', 'Tropical Beaches'].map(i => ({
5656
label: i,
5757
value: i
5858
}))
5959
}
60-
],
61-
pagination_mode: false,
60+
},
61+
page_action: TableAction.None,
6262
style_table: {
6363
max_height: '800px',
6464
height: '800px',
@@ -77,24 +77,23 @@ function getBaseTableProps(mock: IDataMock) {
7777
function getDefaultState(
7878
generateData: Function = generateMockData
7979
): {
80-
filter: string,
80+
filter_query: string,
8181
tableProps: Partial<PropsWithDefaults>
8282
} {
8383
const mock = generateData(5000);
8484

8585
return {
86-
filter: '',
86+
filter_query: '',
8787
tableProps: R.merge(getBaseTableProps(mock), {
8888
data: mock.data,
8989
editable: true,
90-
sorting: true,
91-
n_fixed_rows: 3,
92-
n_fixed_columns: 2,
90+
sort_action: TableAction.Native,
91+
fixed_rows: { headers: true },
92+
fixed_columns: { headers: true },
9393
merge_duplicate_headers: false,
9494
row_deletable: true,
9595
row_selectable: 'single',
96-
content_style: ContentStyle.Fit,
97-
pagination_mode: 'fe'
96+
page_action: TableAction.Native
9897
}) as Partial<PropsWithDefaults>
9998
};
10099
}
@@ -113,16 +112,16 @@ function getReadonlyState() {
113112

114113
function getSpaceInColumn() {
115114
const state = getDefaultState(generateSpaceMockData);
116-
state.tableProps.filtering = true;
115+
state.tableProps.filter_action = TableAction.Native;
117116

118117
return state;
119118
}
120119

121120
function getFixedTooltipsState() {
122121
const state = getTooltipsState();
123122

124-
state.tableProps.n_fixed_columns = 3;
125-
state.tableProps.n_fixed_rows = 4;
123+
state.tableProps.fixed_columns = { headers: true, data: 1 };
124+
state.tableProps.fixed_rows = { headers: true, data: 1 };
126125

127126
return state;
128127
}
@@ -132,25 +131,23 @@ function getTooltipsState() {
132131

133132
state.tableProps.tooltip_delay = 250;
134133
state.tableProps.tooltip_duration = 1000;
135-
state.tableProps.tooltips = {
136-
ccc: [
137-
{ type: TooltipSyntax.Markdown, value: `### Go Proverb\nThe enemy's key point is yours` },
138-
{ type: TooltipSyntax.Markdown, value: `### Go Proverb\nPlay on the point of symmetry` },
139-
{ type: TooltipSyntax.Markdown, value: `### Go Proverb\nSente gains nothing` },
140-
{ type: TooltipSyntax.Text, value: `Beware of going back to patch up` },
141-
{ type: TooltipSyntax.Text, value: `When in doubt, Tenuki` },
142-
`People in glass houses shouldn't throw stones`
143-
]
144-
};
145-
state.tableProps.column_static_tooltip = {
134+
state.tableProps.tooltip_data = [
135+
{ ccc: { type: TooltipSyntax.Markdown, value: `### Go Proverb\nThe enemy's key point is yours` } },
136+
{ ccc: { type: TooltipSyntax.Markdown, value: `### Go Proverb\nPlay on the point of symmetry` } },
137+
{ ccc: { type: TooltipSyntax.Markdown, value: `### Go Proverb\nSente gains nothing` } },
138+
{ ccc: { type: TooltipSyntax.Text, value: `Beware of going back to patch up` } },
139+
{ ccc: { type: TooltipSyntax.Text, value: `When in doubt, Tenuki` } },
140+
{ ccc: `People in glass houses should not throw stones` }
141+
];
142+
state.tableProps.tooltip = {
146143
ccc: { type: TooltipSyntax.Text, value: `There is death in the hane` },
147144
ddd: { type: TooltipSyntax.Markdown, value: `Hane, Cut, Placement` },
148145
rows: `Learn the eyestealing tesuji`
149146
};
150-
state.tableProps.column_conditional_tooltips = [{
147+
state.tableProps.tooltip_conditional = [{
151148
if: {
152149
column_id: 'aaa-readonly',
153-
filter: `{aaa} is prime`
150+
filter_query: `{aaa} is prime`
154151
},
155152
type: TooltipSyntax.Markdown,
156153
value: `### Go Proverbs\nCapture three to get an eye`
@@ -218,7 +215,7 @@ function getDateState() {
218215

219216
function getFilteringState() {
220217
const state = getDefaultState();
221-
state.tableProps.filtering = true;
218+
state.tableProps.filter_action = TableAction.Native;
222219

223220
return state;
224221
}
@@ -227,15 +224,14 @@ function getVirtualizedState() {
227224
const mock = generateMockData(5000);
228225

229226
return {
230-
filter: '',
227+
filter_query: '',
231228
tableProps: R.merge(getBaseTableProps(mock), {
232229
data: mock.data,
233230
editable: true,
234-
sorting: true,
231+
sort_action: TableAction.Native,
235232
merge_duplicate_headers: false,
236233
row_deletable: true,
237234
row_selectable: 'single',
238-
content_style: 'fit',
239235
virtualization: true
240236
})
241237
};
@@ -245,17 +241,16 @@ function getFixedVirtualizedState() {
245241
const mock = generateMockData(5000);
246242

247243
return {
248-
filter: '',
244+
filter_query: '',
249245
tableProps: R.merge(getBaseTableProps(mock), {
250246
data: mock.data,
251247
editable: true,
252-
sorting: true,
253-
n_fixed_rows: 3,
254-
n_fixed_columns: 2,
248+
sort_action: TableAction.Native,
249+
fixed_rows: { headers: true },
250+
fixed_columns: { headers: true },
255251
merge_duplicate_headers: false,
256252
row_deletable: true,
257253
row_selectable: 'single',
258-
content_style: 'fit',
259254
virtualization: true
260255
})
261256
};

demo/data.ts

-7
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ export const generateMockData = (rows: number) => unpackIntoColumnsAndData([
5858
name: ['', 'Weather', 'Climate'],
5959
type: ColumnType.Text,
6060
presentation: 'dropdown',
61-
clearable: true,
6261
data: gendata(
6362
i => ['Humid', 'Wet', 'Snowy', 'Tropical Beaches'][i % 4],
6463
rows
@@ -141,7 +140,6 @@ export const generateSpaceMockData = (rows: number) => unpackIntoColumnsAndData(
141140
name: ['', 'Weather', 'Climate'],
142141
type: ColumnType.Text,
143142
presentation: 'dropdown',
144-
clearable: true,
145143
data: gendata(
146144
i => ['Humid', 'Wet', 'Snowy', 'Tropical Beaches'][i % 4],
147145
rows
@@ -162,11 +160,6 @@ export const mockDataSimple = (rows: number) => unpackIntoColumnsAndData([
162160
name: 'Climate',
163161
type: ColumnType.Text,
164162
presentation: 'dropdown',
165-
options: ['Humid', 'Wet', 'Snowy', 'Tropical Beaches'].map(i => ({
166-
label: i,
167-
value: i
168-
})),
169-
clearable: true,
170163
data: gendata(
171164
i => ['Humid', 'Wet', 'Snowy', 'Tropical Beaches'][i % 4],
172165
rows

generator/cssPropertiesGenerator.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ camels.forEach(([camel]) => map.set(camel, camel));
302302

303303
const fs = require('fs');
304304

305-
var stream1 = fs.createWriteStream("src/dash-table/derived/style/py2jsCssProperties.ts");
305+
var stream1 = fs.createWriteStream('src/dash-table/derived/style/py2jsCssProperties.ts');
306306
stream1.once('open', () => {
307307
stream1.write('export type StyleProperty = string | number;\n');
308308
stream1.write('\n');
@@ -317,25 +317,25 @@ stream1.once('open', () => {
317317
first = false;
318318
stream1.write(` ['${key}', '${value}']`);
319319
});
320-
stream1.write('\n]);')
320+
stream1.write('\n]);');
321321

322322
stream1.end();
323323
});
324324

325-
var stream2 = fs.createWriteStream("src/dash-table/derived/style/IStyle.ts");
325+
var stream2 = fs.createWriteStream('src/dash-table/derived/style/IStyle.ts');
326326
stream2.once('open', () => {
327327
stream2.write(`import { StyleProperty } from './ py2jsCssProperties';\n`);
328328
stream2.write('\n');
329329
stream2.write('export default interface IStyle {\n');
330330
camels.forEach(([key]) => {
331331
stream2.write(` ${key}: StyleProperty;\n`);
332332
});
333-
stream2.write('}')
333+
stream2.write('}');
334334

335335
stream2.end();
336336
});
337337

338-
var stream3 = fs.createWriteStream("proptypes.js");
338+
var stream3 = fs.createWriteStream('proptypes.js');
339339
stream3.once('open', () => {
340340
let first = true;
341341
map.forEach((value, key) => {
@@ -350,7 +350,7 @@ stream3.once('open', () => {
350350
stream3.write(` ${key}: PropTypes.oneOfType([PropTypes.string, PropTypes.number])`);
351351
}
352352
});
353-
stream3.write('\n')
353+
stream3.write('\n');
354354

355355
stream3.end();
356356
});

0 commit comments

Comments
 (0)