Skip to content

Selecting a column or a shift+click range in gr.Dataframe while a search is active edits rows that are not shown #13791

Description

@hysts

Describe the bug

While show_search="search" is filtering the table, two selection paths put rows into the selection that the search is hiding. Copying or pressing Delete then hits those hidden rows instead of, or in addition to, the ones on screen.

Selecting a column. The "Select column" button builds the selection out of positions in the filtered view and stores them as row indices into the data:

selected_cells = rows.map((_, r) => [r, c]);

rows is the filtered row model, so with 20 rows showing this selects data rows 0 to 19 no matter which rows the search left visible. Everything that consumes selected_cells (the highlight, copy, Delete) treats those numbers as indices into the underlying data, so the selection lands somewhere else entirely. Pressing Delete afterwards clears rows that were never on screen and leaves the ones that were.

Shift+click. The range in handle_cell_click is built in data space:

for (let r = Math.min(r1, r2); r <= Math.max(r1, r2); r++) { ... }

Shift-clicking two visible rows therefore also selects every row between them that the search is hiding. Whether a range drawn across a filter should include the hidden rows is arguably a design call, but the highlight and the effect disagree either way: the hidden rows are never rendered, so they cannot be highlighted, and there is no way to see what is actually selected before pressing Delete. Restricting the range to the rows the search shows seems the reasonable reading, but that call is yours.

Both are the same data-index versus view-index confusion as #11022, but in the selection paths rather than the scroll path.

Have you searched existing issues? 🔎

  • I have searched and found no existing issues

Reproduction

import gradio as gr

# even rows match the search, odd rows do not
data = [[i, "target" if i % 2 == 0 else f"keep-{i}"] for i in range(40)]

with gr.Blocks() as demo:
    gr.Dataframe(
        value=data,
        headers=["idx", "tag"],
        interactive=True,
        show_search="search",
    )

demo.launch()

Search for target, so that only the 20 even rows are shown.

Column select. Click any cell in the tag column of the row with idx 20, then press the small arrow button that appears above the cell (the "Select column" button, next to the "Select row" one on the cell's left edge). Only the rows with idx 0 to 18 highlight, and the row you started from is not among them. Press Delete: the tag values of rows 0 to 19 are cleared, including the odd rows the search was hiding, while rows 20 to 38 keep their value. Clear the search to see it.

Shift+click. Reload, search target again, click the tag cell of row 0, then shift-click the tag cell of row 4. Rows 0, 2 and 4 highlight, which is what you would expect. Press Delete and clear the search: rows 1 and 3 have been cleared as well.

Expected in both cases: only the rows the search is showing are selected and edited.

Screenshot

No response

Logs

System Info

gradio 6.26.0 (built from main)
Python 3.13.12
Chrome

Severity

I can work around it

Activity

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions