Skip to content

feat(table): add default_sort for mo.ui.table initial ordering#8882

Open
phusi319 wants to merge 2 commits intomarimo-team:mainfrom
phusi319:feat/table-default-sort-3860
Open

feat(table): add default_sort for mo.ui.table initial ordering#8882
phusi319 wants to merge 2 commits intomarimo-team:mainfrom
phusi319:feat/table-default-sort-3860

Conversation

@phusi319
Copy link
Copy Markdown

Closes #3860

This PR adds support for default_sort in mo.ui.table to control initial table ordering.

Summary

  • Backend (marimo/_plugins/ui/_impl/table.py)
    • Adds a default_sort argument to ui.table.
    • Validates that the requested sort column exists in table columns.
    • Applies initial search sorting with ascending order by default.
    • Exposes default-sort in component args for frontend initialization.
  • Frontend (frontend/src/plugins/impl/DataTablePlugin.tsx)
    • Accepts defaultSort in plugin schema/data.
    • Initializes table sorting state from defaultSort as ascending (desc: false).
  • Tests (tests/_plugins/ui/_impl/test_table.py)
    • Adds coverage that initial render uses default_sort ordering.
    • Adds validation test that missing default_sort column raises an error.

Behavior note: sorting is ascending by default when default_sort is provided.

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>
Copilot AI review requested due to automatic review settings March 26, 2026 14:48
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 26, 2026

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
marimo-docs Ready Ready Preview, Comment Mar 26, 2026 3:07pm

Request Review

@phusi319
Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 expose default-sort to the web component.
  • Frontend: accept defaultSort and 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.

Comment on lines 472 to 474
default_sort: Optional[str] = None,
max_columns: MaxColumnsType = MAX_COLUMNS_NOT_PROVIDED,
*,
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
default_sort: Optional[str] = None,
max_columns: MaxColumnsType = MAX_COLUMNS_NOT_PROVIDED,
*,
max_columns: MaxColumnsType = MAX_COLUMNS_NOT_PROVIDED,
*,
default_sort: Optional[str] = None,

Copilot uses AI. Check for mistakes.
Comment on lines +679 to +686
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"
)

Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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:

Copilot uses AI. Check for mistakes.
);
// Sorting/searching state
const [sorting, setSorting] = useState<SortingState>([]);
const [sorting, setSorting] = useState<SortingState>(initialSorting);
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Suggested change
const [sorting, setSorting] = useState<SortingState>(initialSorting);
const [sorting, setSorting] = useState<SortingState>(Arrays.EMPTY);

Copilot uses AI. Check for mistakes.
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>
@phusi319
Copy link
Copy Markdown
Author

Thank you for the thorough review! I believe all three concerns have been addressed in the current code:

1. Breaking change - default_sort parameter position

The parameter is already keyword-only (placed after *, at line 473-474):
python max_columns: MaxColumnsType = MAX_COLUMNS_NOT_PROVIDED, *, default_sort: Optional[str] = None,
This preserves backwards compatibility since callers cannot pass it positionally.

2. Validation consistency with _internal_lazy

The validation runs regardless of _internal_lazy (lines 679-684):
`python
if default_sort is not None:
existing_columns = set(self._manager.get_column_names())
if default_sort not in existing_columns:
raise ValueError(...)

if not _internal_lazy: # <-- validation above is outside this block
...
`

3. Frontend initial page fast-path

The canShowInitialPage logic (lines 570-580) handles the default sort case:
javascript const canShowInitialPage = searchQuery === "" && paginationState.pageIndex === 0 && filters.length === 0 && (sorting.length === 0 || (sorting.length === 1 && Boolean(props.defaultSort) && sorting[0]?.id === props.defaultSort && sorting[0]?.desc === false)) && // Allow initial page when sort matches defaultSort !props.lazy && !pageSizeChanged;
This allows the fast-path when sorting exactly matches the default sort, avoiding unnecessary latency.

Let me know if I've misunderstood any of the feedback!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add default_sort parameter to mo.ui.table

2 participants