feat(table): add default_sort for mo.ui.table initial ordering#8882
feat(table): add default_sort for mo.ui.table initial ordering#8882phusi319 wants to merge 2 commits intomarimo-team:mainfrom
Conversation
Expose default_sort in mo.ui.table, apply ascending default initial sort on first render, and validate unknown columns with ValueError. Also wire frontend initial sorting state and add targeted tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
All contributors have signed the CLA ✍️ ✅ |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
I have read the CLA Document and I hereby sign the CLA |
There was a problem hiding this comment.
Pull request overview
Adds a default_sort option to mo.ui.table to control initial ordering, plumbing the setting through backend table initialization and frontend sorting state, with backend tests to validate behavior.
Changes:
- Backend: add
default_sort, validate column existence, apply initial ascending sort, and exposedefault-sortto the web component. - Frontend: accept
defaultSortand initialize the table’s sorting state from it (ascending). - Tests: cover initial ordering and invalid-column validation.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
marimo/_plugins/ui/_impl/table.py |
Adds default_sort arg, validates it, applies initial sort to first-page data, and emits data-default-sort. |
frontend/src/plugins/impl/DataTablePlugin.tsx |
Extends plugin schema with defaultSort and initializes TanStack sorting state from it. |
tests/_plugins/ui/_impl/test_table.py |
Adds tests for initial default sort ordering and invalid default_sort error. |
marimo/_plugins/ui/_impl/table.py
Outdated
| default_sort: Optional[str] = None, | ||
| max_columns: MaxColumnsType = MAX_COLUMNS_NOT_PROVIDED, | ||
| *, |
There was a problem hiding this comment.
default_sort was inserted before max_columns in the positional parameter list. This is a breaking change for any callers passing max_columns positionally (it will now be interpreted as default_sort). To preserve backwards compatibility, consider making default_sort keyword-only (move it after *) or place it after max_columns in the signature.
| default_sort: Optional[str] = None, | |
| max_columns: MaxColumnsType = MAX_COLUMNS_NOT_PROVIDED, | |
| *, | |
| max_columns: MaxColumnsType = MAX_COLUMNS_NOT_PROVIDED, | |
| *, | |
| default_sort: Optional[str] = None, |
marimo/_plugins/ui/_impl/table.py
Outdated
| if not _internal_lazy: | ||
| if default_sort is not None: | ||
| existing_columns = set(self._manager.get_column_names()) | ||
| if default_sort not in existing_columns: | ||
| raise ValueError( | ||
| f"default_sort column '{default_sort}' not found in table columns" | ||
| ) | ||
|
|
There was a problem hiding this comment.
Validation for default_sort currently runs only when not _internal_lazy. If default_sort is ever provided with _internal_lazy=True, the invalid column will be silently ignored (since _apply_filters_query_sort drops unknown sort columns) rather than raising as documented/tested. Consider validating default_sort regardless of _internal_lazy to keep behavior consistent.
| if not _internal_lazy: | |
| if default_sort is not None: | |
| existing_columns = set(self._manager.get_column_names()) | |
| if default_sort not in existing_columns: | |
| raise ValueError( | |
| f"default_sort column '{default_sort}' not found in table columns" | |
| ) | |
| if default_sort is not None: | |
| existing_columns = set(self._manager.get_column_names()) | |
| if default_sort not in existing_columns: | |
| raise ValueError( | |
| f"default_sort column '{default_sort}' not found in table columns" | |
| ) | |
| if not _internal_lazy: |
| ); | ||
| // Sorting/searching state | ||
| const [sorting, setSorting] = useState<SortingState>([]); | ||
| const [sorting, setSorting] = useState<SortingState>(initialSorting); |
There was a problem hiding this comment.
Initializing sorting state from defaultSort makes sorting.length !== 0 on mount, which forces canShowInitialPage to be false and causes the first render to await search() instead of displaying the precomputed initial page. This can add avoidable latency/loader flashes even though the backend already sends sorted initial data. Consider updating the initial-page fast-path to treat the default sort as part of the initial state (or keep sorting empty while still showing the UI sort indicator).
| const [sorting, setSorting] = useState<SortingState>(initialSorting); | |
| const [sorting, setSorting] = useState<SortingState>(Arrays.EMPTY); |
Make default_sort keyword-only to preserve positional compatibility, validate default_sort in lazy mode, and keep initial-page fast-path when default sort is active. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Thank you for the thorough review! I believe all three concerns have been addressed in the current code: 1. Breaking change -
|
Closes #3860
This PR adds support for
default_sortinmo.ui.tableto control initial table ordering.Summary
marimo/_plugins/ui/_impl/table.py)default_sortargument toui.table.default-sortin component args for frontend initialization.frontend/src/plugins/impl/DataTablePlugin.tsx)defaultSortin plugin schema/data.defaultSortas ascending (desc: false).tests/_plugins/ui/_impl/test_table.py)default_sortordering.default_sortcolumn raises an error.Behavior note: sorting is ascending by default when
default_sortis provided.