[GH-ISSUE #768] Table pagination with fixed rows #561

Closed
opened 2026-03-04 01:06:01 +03:00 by kerem · 5 comments
Owner

Originally created by @carpii on GitHub (Nov 13, 2022).
Original GitHub issue: https://github.com/rivo/tview/issues/768

Create a table with lots of rows, and a single fixed row....

func main() {
	app := tview.NewApplication()
	table := tview.NewTable().SetBorders(false).SetSelectable(true, false).SetFixed(1, 0)
	table.SetCell(0, 0, tview.NewTableCell("Fixed Row").SetTextColor(tcell.ColorBlack).SetBackgroundColor(tcell.ColorDarkBlue).SetAlign(tview.AlignLeft))

	for i := 1; i < 200; i++ {
		table.SetCell(i, 0, tview.NewTableCell("Row "+strconv.Itoa(i)))
	}
	if err := app.SetRoot(table, true).Run(); err != nil {
		panic(err)
	}
}

Now page down twice, and page up twice

You would expect the table to be showing row 1 again. Instead what happens is that you select the fixed row, but the table body is still showing some rows from page 2.

As a workaround I change https://github.com/rivo/tview/blob/master/table.go#L1526

	if t.selectedRow < 0 {
		t.selectedRow = 0
	}

to

	if t.selectedRow < t.fixedRows {
		t.selectedRow = t.fixedRows
	}

But it's probably not the correct solution (I only just started using tview today). Thanks for the great library!

Originally created by @carpii on GitHub (Nov 13, 2022). Original GitHub issue: https://github.com/rivo/tview/issues/768 Create a table with lots of rows, and a single fixed row.... ```` func main() { app := tview.NewApplication() table := tview.NewTable().SetBorders(false).SetSelectable(true, false).SetFixed(1, 0) table.SetCell(0, 0, tview.NewTableCell("Fixed Row").SetTextColor(tcell.ColorBlack).SetBackgroundColor(tcell.ColorDarkBlue).SetAlign(tview.AlignLeft)) for i := 1; i < 200; i++ { table.SetCell(i, 0, tview.NewTableCell("Row "+strconv.Itoa(i))) } if err := app.SetRoot(table, true).Run(); err != nil { panic(err) } } ```` Now page down twice, and page up twice You would expect the table to be showing row 1 again. Instead what happens is that you select the fixed row, but the table body is still showing some rows from page 2. As a workaround I change https://github.com/rivo/tview/blob/master/table.go#L1526 ```` if t.selectedRow < 0 { t.selectedRow = 0 } ```` to ```` if t.selectedRow < t.fixedRows { t.selectedRow = t.fixedRows } ```` But it's probably not the correct solution (I only just started using tview today). Thanks for the great library!
kerem closed this issue 2026-03-04 01:06:01 +03:00
Author
Owner

@rivo commented on GitHub (Nov 14, 2022):

Colouring the fixed row blue with a black background kind of obscures the fact you're selecting that fixed row, too. It's selected initially and then again after hitting Page Down two times and Page Up two times. So the selection goes exactly where it's supposed to. (Make its text red to better see what's going on.)

Whether selecting a fixed row should also reset the scroll offset to 0 is debatable. I would say no. I can think of cases where you'd want to select a cell in a fixed row without at the same time having the entire table scroll back to the beginning.

In your specific case, unless you need the fixed row to be selectable, I would suggest making it unselectable:

table.SetCell(0, 0, tview.NewTableCell("Fixed Row").
	SetTextColor(tcell.ColorRed).
	SetAlign(tview.AlignLeft).
	SetSelectable(false))

Now your selection starts with the second row and paging down and up again will have the intended behaviour.

<!-- gh-comment-id:1313899434 --> @rivo commented on GitHub (Nov 14, 2022): Colouring the fixed row blue with a black background kind of obscures the fact you're selecting that fixed row, too. It's selected initially and then again after hitting Page Down two times and Page Up two times. So the selection goes exactly where it's supposed to. (Make its text red to better see what's going on.) Whether selecting a fixed row should also reset the scroll offset to 0 is debatable. I would say no. I can think of cases where you'd want to select a cell in a fixed row without at the same time having the entire table scroll back to the beginning. In your specific case, unless you need the fixed row to be selectable, I would suggest making it unselectable: ```golang table.SetCell(0, 0, tview.NewTableCell("Fixed Row"). SetTextColor(tcell.ColorRed). SetAlign(tview.AlignLeft). SetSelectable(false)) ``` Now your selection starts with the second row and paging down and up again will have the intended behaviour.
Author
Owner

@carpii commented on GitHub (Nov 14, 2022):

I hadn't yet spotted the TableCell.SetSelected() api. Thats working much better, thanks

If I have a table of 1 unselectable fixed row, + 6 selectable rows, would you expect page up to always select the top selectable row?
This seems to work, unless the very last row is selected at which point it does nothing

<!-- gh-comment-id:1314008298 --> @carpii commented on GitHub (Nov 14, 2022): I hadn't yet spotted the TableCell.SetSelected() api. Thats working much better, thanks If I have a table of 1 unselectable fixed row, + 6 selectable rows, would you expect page up to always select the top selectable row? This seems to work, unless the very last row is selected at which point it does nothing
Author
Owner

@rivo commented on GitHub (Nov 15, 2022):

If I have a table of 1 unselectable fixed row, + 6 selectable rows, would you expect page up to always select the top selectable row?

Depends on which row is currently selected and how tall your Table element is. I would expect the select to move up by the number of visible rows.

This seems to work, unless the very last row is selected at which point it does nothing

Can you post an example that illustrates this?

<!-- gh-comment-id:1315448321 --> @rivo commented on GitHub (Nov 15, 2022): > If I have a table of 1 unselectable fixed row, + 6 selectable rows, would you expect page up to always select the top selectable row? Depends on which row is currently selected and how tall your `Table` element is. I would expect the select to move up by the number of visible rows. > This seems to work, unless the very last row is selected at which point it does nothing Can you post an example that illustrates this?
Author
Owner

@carpii commented on GitHub (Nov 15, 2022):

package main

import (
	"strconv"

	"github.com/gdamore/tcell/v2"
	"github.com/rivo/tview"
)

func main() {
	app := tview.NewApplication()
	table := tview.NewTable().SetSelectable(true, false).SetFixed(1, 0)
	table.SetCell(0, 0, tview.NewTableCell("Header").SetBackgroundColor(tcell.ColorDarkBlue).SetSelectable(false))

	for i := 1; i < 6; i++ {
		table.SetCell(i, 0, tview.NewTableCell("Row "+strconv.Itoa(i)))
	}
	if err := app.SetRoot(table, true).Run(); err != nil {
		panic(err)
	}
}

Assuming term is big enough to view all rows...

If you select Row 2-4 and press Page Up, selection jumps to Row 1 as I'd expect.
If you select Row 5 and Page Up, table selection does not change

<!-- gh-comment-id:1315492936 --> @carpii commented on GitHub (Nov 15, 2022): ```` package main import ( "strconv" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" ) func main() { app := tview.NewApplication() table := tview.NewTable().SetSelectable(true, false).SetFixed(1, 0) table.SetCell(0, 0, tview.NewTableCell("Header").SetBackgroundColor(tcell.ColorDarkBlue).SetSelectable(false)) for i := 1; i < 6; i++ { table.SetCell(i, 0, tview.NewTableCell("Row "+strconv.Itoa(i))) } if err := app.SetRoot(table, true).Run(); err != nil { panic(err) } } ```` Assuming term is big enough to view all rows... If you select Row 2-4 and press Page Up, selection jumps to Row 1 as I'd expect. If you select Row 5 and Page Up, table selection does not change
Author
Owner

@rivo commented on GitHub (Nov 17, 2022):

Good catch! The latest commit should fix this.

Thanks for posting code to reproduce this.

<!-- gh-comment-id:1318170789 --> @rivo commented on GitHub (Nov 17, 2022): Good catch! The latest commit should fix this. Thanks for posting code to reproduce this.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/tview#561
No description provided.