textual
textual copied to clipboard
Document Suggester in Input
The Input widget docs don't cover Suggesters, other than a reference in the API. It is such a useful feature I think it deserves a section with a simple demo.
Yes this is very useful. Also some screenshots with visual examples will be great.
Could I suggest that something more simple and more generic be considered?
A watcher on input should be able to fire on one of two conditions: any change (key press, paste, cut) or any completion (blur or enter). A watcher should be able to be boolean (just disallow the changes) or return a pair with (optional new value, optional new renderable instead of just rendering the value). This allows for suggesters, regex validation, type ahead, complex highlighting like different parts of a url, complex validation like being sure the part number is in stock, and pretty much every use case.
A Suggester just becomes one of the watchers.
Could you share a quick code snippet of what that might look like in a new discussion @merriam? I'm struggling to visualize it.
Hi!
I was exploring the issues page when I found this thread and I came out with an example about a shopping list. At first I was trying to come up with something which used the Suggester instead of the SuggestFromList but I couldn't think of any use case that would fit in a simple example. I also thought that the most common use case would be to use a list as the source of the suggestion anyways.
from textual import on
from textual.app import App, ComposeResult
from textual.suggester import SuggestFromList
from textual.widgets import Input, Label, ListItem, ListView
products = [
"milk",
"eggs",
"bread",
"butter",
"cheese",
"fruits",
"vegetables",
"chicken",
]
class ShoppingListApp(App):
def compose(self) -> ComposeResult:
yield Input(
placeholder="Product",
suggester=SuggestFromList(suggestions=products, case_sensitive=False),
)
yield ListView()
@on(Input.Submitted)
def add_item_to_list(self, event: Input.Submitted) -> None:
list_item = ListItem(Label(event.value))
self.query_one(ListView).mount(list_item)
if __name__ == "__main__":
app = ShoppingListApp()
app.run()