tview icon indicating copy to clipboard operation
tview copied to clipboard

Get table row and column from inputfield

Open jacques-andre opened this issue 3 years ago • 2 comments

I am creating a Sudoku game where a user is able to select a cell in a table and using a inputField able to input a value for that cell.

I am having difficulties getting the selected row and column from the user and passing it to my inputField.

I want my inputField to be able to change the current cell's value.

package main

import (
	"strconv"

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

func main() {
	grid := [9][9]int{}

	app := tview.NewApplication()
	test := tview.NewTextView()
	table := tview.NewTable().SetBorders(true)
	table.SetSelectable(true, true)

	// create a table
	for row := 0; row < len(grid); row++ {
		for col := 0; col < len(grid[row]); col++ {
			currentBoardValue := grid[row][col]
			newCell := tview.NewTableCell(strconv.Itoa(currentBoardValue))

			// add new cell to table
			table.SetCell(row, col, newCell)
		}
	}

	// create inputField with titles
	inputField := tview.NewInputField().
		SetLabel("Enter a number: ").
		SetFieldWidth(10).
		SetAcceptanceFunc(tview.InputFieldInteger)

	// When enter is pressed on input
	inputField.SetDoneFunc(func(key tcell.Key) {
		app.SetFocus(table)
		// how can i get the table row and col here?

		test.SetText(inputField.GetText())
		inputField.SetText("")
	})

	tviewGrid := tview.NewGrid().SetBorders(true)

	tviewGrid.AddItem(table, 0, 0, 2, 1, 1, 1, true)
	tviewGrid.AddItem(inputField, 2, 0, 2, 1, 1, 1, false)
	tviewGrid.AddItem(test, 0, 1, 2, 1, 1, 1, false)

	// when cell is selected
	table.SetSelectedFunc(func(row int, col int) {

		// set the focus to input
		app.SetFocus(inputField)

		// I want to be able to update the selcted cell based off inputField, this doesn't work

		table.GetCell(row, col).SetText(inputField.GetText())

	})
	// run the app
	err := app.SetRoot(tviewGrid, true).EnableMouse(false).Run()
	if err != nil {
		panic(err)
	}
}

jacques-andre avatar Apr 18 '22 18:04 jacques-andre

Hi,

// how can i get the table row and col here?
r, c := table.GetSelection()       // returns selected cell coordinates
cell := table.GetCell(r, c)        // gets cell from coordinates
cell.SetText(inputField.GetText()) // set cell value from input field
// I want to be able to update the selcted cell based off inputField, this doesn't work

table.GetCell(row, col).SetText(inputField.GetText())

With the change above you probably don't want to do this at all...

Full code
package main

import (
	"strconv"

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

func main() {
	grid := [9][9]int{}

	app := tview.NewApplication()
	test := tview.NewTextView()
	table := tview.NewTable().SetBorders(true)
	table.SetSelectable(true, true)

	// create a table
	for row := 0; row < len(grid); row++ {
		for col := 0; col < len(grid[row]); col++ {
			currentBoardValue := grid[row][col]
			newCell := tview.NewTableCell(strconv.Itoa(currentBoardValue))

			// add new cell to table
			table.SetCell(row, col, newCell)
		}
	}

	// create inputField with titles
	inputField := tview.NewInputField().
		SetLabel("Enter a number: ").
		SetFieldWidth(10).
		SetAcceptanceFunc(tview.InputFieldInteger)

	// When enter is pressed on input
	inputField.SetDoneFunc(func(key tcell.Key) {
		app.SetFocus(table)
		r, c := table.GetSelection()       // returns selected cell coordinates
		cell := table.GetCell(r, c)        // gets cell from coordinates
		cell.SetText(inputField.GetText()) // set cell value from input
	})

	tviewGrid := tview.NewGrid().SetBorders(true)

	tviewGrid.AddItem(table, 0, 0, 2, 1, 1, 1, true)
	tviewGrid.AddItem(inputField, 2, 0, 2, 1, 1, 1, false)
	tviewGrid.AddItem(test, 0, 1, 2, 1, 1, 1, false)

	// when cell is selected
	table.SetSelectedFunc(func(row int, col int) {

		// set the focus to input
		app.SetFocus(inputField)

		// I want to be able to update the selcted cell based off inputField, this doesn't work

		//table.GetCell(row, col).SetText(inputField.GetText())

	})
	// run the app
	err := app.SetRoot(tviewGrid, true).EnableMouse(false).Run()
	if err != nil {
		panic(err)
	}
}

moson-mo avatar Jun 06 '22 19:06 moson-mo

@jacques-andre You're setting the text of the table cell too early. When the selected func is executed, there is no text yet in the input field. You have to wait for the user to enter it. There are many ways to solve this. Here's one way:

package main

import (
	"strconv"

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

func main() {
	grid := [9][9]int{}

	app := tview.NewApplication()
	test := tview.NewTextView()
	table := tview.NewTable().SetBorders(true)
	table.SetSelectable(true, true)

	// create a table
	for row := 0; row < len(grid); row++ {
		for col := 0; col < len(grid[row]); col++ {
			currentBoardValue := grid[row][col]
			newCell := tview.NewTableCell(strconv.Itoa(currentBoardValue))

			// add new cell to table
			table.SetCell(row, col, newCell)
		}
	}

	// create inputField with titles
	inputField := tview.NewInputField().
		SetLabel("Enter a number: ").
		SetFieldWidth(10).
		SetAcceptanceFunc(func(text string, ch rune) bool {
			return len(text) <= 1 && ch >= '1' && ch <= '9' // Sudoku only allows 1-9.
		})

	tviewGrid := tview.NewGrid().SetBorders(true)

	tviewGrid.AddItem(table, 0, 0, 2, 1, 1, 1, true)
	tviewGrid.AddItem(inputField, 2, 0, 2, 1, 1, 1, false)
	tviewGrid.AddItem(test, 0, 1, 2, 1, 1, 1, false)

	// when cell is selected
	table.SetSelectedFunc(func(row int, col int) {

		inputField.SetText("")
		app.SetFocus(inputField)

		inputField.SetDoneFunc(func(key tcell.Key) {
			table.GetCell(row, col).SetText(inputField.GetText())
			inputField.SetText("")
			app.SetFocus(table)
		})

	})
	// run the app
	err := app.SetRoot(tviewGrid, true).EnableMouse(false).Run()
	if err != nil {
		panic(err)
	}
}

rivo avatar Jun 10 '22 15:06 rivo