[GH-ISSUE #147] InputField should verify all input changes with func accept() #117

Closed
opened 2026-03-04 01:02:04 +03:00 by kerem · 4 comments
Owner

Originally created by @ardnew on GitHub (Jul 30, 2018).
Original GitHub issue: https://github.com/rivo/tview/issues/147

Currently, InputField will conditionally permit any input changes using the user-provided callback accept(), but only if the input is a regular character (i.e. event.Key() == tcell.KeyRune). This means the callback cannot be used to conditionally permit control characters like backspace.

A simple example is the callback function that renders an InputField read-only:

rejectInput := func(string, rune) bool { return false }

form := tview.NewForm()
form.AddInputField("foo", "bar", 0, rejectInput, nil)

This will prevent new characters from being inserted, but it won't prevent characters from being deleted. In fact, I don't think there exists a way to prevent the user from deleting text in an InputField (I could be wrong on this point).

The same loophole exists for the key-combos Ctrl+U and Ctrl+W.

Originally created by @ardnew on GitHub (Jul 30, 2018). Original GitHub issue: https://github.com/rivo/tview/issues/147 Currently, `InputField` will conditionally permit any input changes using the user-provided callback `accept()`, but only if the input is a regular character (i.e. `event.Key() == tcell.KeyRune`). This means the callback cannot be used to conditionally permit control characters like backspace. A simple example is the callback function that renders an `InputField` read-only: ``` rejectInput := func(string, rune) bool { return false } form := tview.NewForm() form.AddInputField("foo", "bar", 0, rejectInput, nil) ``` This will prevent new characters from being inserted, but it won't prevent characters from being deleted. In fact, I don't think there exists a way to prevent the user from deleting text in an `InputField` (I could be wrong on this point). The same loophole exists for the key-combos Ctrl+U and Ctrl+W.
kerem closed this issue 2026-03-04 01:02:05 +03:00
Author
Owner

@ardnew commented on GitHub (Jul 30, 2018):

I also considered bringing the accept() handler outside (immediately before) the switch key := event.Key(); key { ... } block - so that it can be used to evaluate all input changes and not just the few I updated; but I wasn't sure if that kept with the spirit of your intent with that callback (since you wouldn't be able to pass in the changed text to evaluate).

Perhaps a different callback should be created, or even subclassing the InputField might be preferred if you need that much control?

<!-- gh-comment-id:409021219 --> @ardnew commented on GitHub (Jul 30, 2018): I also considered bringing the `accept()` handler outside (immediately before) the `switch key := event.Key(); key { ... }` block - so that it can be used to evaluate _all_ input changes and not just the few I updated; but I wasn't sure if that kept with the spirit of your intent with that callback (since you wouldn't be able to pass in the _changed_ text to evaluate). Perhaps a different callback should be created, or even subclassing the `InputField` might be preferred if you need that much control?
Author
Owner

@rivo commented on GitHub (Aug 7, 2018):

The accept() function is not meant to be a filter on the user's keyboard actions but rather on the final text of the InputField.

If you would like to intercept certain keys, you'll want to use SetInputCapture() on the InputField.

Note that I will add more key combinations in the future and a backspace will then not only affect the last character. See #103.

Let me know if this helps.

<!-- gh-comment-id:410963347 --> @rivo commented on GitHub (Aug 7, 2018): The `accept()` function is not meant to be a filter on the user's keyboard actions but rather on the final text of the `InputField`. If you would like to intercept certain keys, you'll want to use [`SetInputCapture()`](https://godoc.org/github.com/rivo/tview#Box.SetInputCapture) on the `InputField`. Note that I will add more key combinations in the future and a backspace will then not only affect the last character. See #103. Let me know if this helps.
Author
Owner

@ardnew commented on GitHub (Aug 7, 2018):

Ah, I've been misusing that callback. Thanks

Somewhat related -- can you clarify the difference or describe how I should choose between using SetInputCapture() versus overriding InputHandler() for the case that I have a type with an embedded primitive (e.g. type MyTable struct { *tview.Table })?

The docs say that defining InputHandler() a certain way allows the use of SetInputCapture(), but I don't understand why I would want or need to use one over the other. They appear to function the same and serve the same purpose.

<!-- gh-comment-id:411119695 --> @ardnew commented on GitHub (Aug 7, 2018): Ah, I've been misusing that callback. Thanks Somewhat related -- can you clarify the difference or describe how I should choose between using `SetInputCapture()` versus overriding `InputHandler()` for the case that I have a type with an embedded primitive (e.g. `type MyTable struct { *tview.Table }`)? [The docs](https://github.com/rivo/tview/wiki/Primitives) say that defining `InputHandler()` a certain way allows the use of `SetInputCapture()`, but I don't understand why I would want or need to use one over the other. They appear to function the same and serve the same purpose.
Author
Owner

@rivo commented on GitHub (Aug 12, 2018):

Unless you are writing your own Primitive, you can ignore InputHandler(). Most applications will be fine using an existing primitive (e.g. InputField) and calling SetInputCapture() to change its input behaviour.

It's only when you end up writing your own Primitive that you'll need to implement InputHandler() and the Wiki page you refer to gives you hints as to how to structure your code in that case.

But I would think that writing one's own Primitive is usually not needed.

I'm closing this issue. If there's still an open item, I can reopen it.

<!-- gh-comment-id:412359013 --> @rivo commented on GitHub (Aug 12, 2018): Unless you are writing your own `Primitive`, you can ignore `InputHandler()`. Most applications will be fine using an existing primitive (e.g. `InputField`) and calling `SetInputCapture()` to change its input behaviour. It's only when you end up writing your own `Primitive` that you'll need to implement `InputHandler()` and the [Wiki page](https://github.com/rivo/tview/wiki/Primitives#writing-primitives) you refer to gives you hints as to how to structure your code in that case. But I would think that writing one's own `Primitive` is usually not needed. I'm closing this issue. If there's still an open item, I can reopen it.
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#117
No description provided.