huh
huh copied to clipboard
Dynamic Inputs
Dynamic Forms

huh?
forms can now react to changes in other parts of the form. Replace
properties such as Options
, Title
, Description
with their dynamic
counterparts: OptionsFunc
, TitleFunc
, and DescriptionFunc
to recompute
properties values on changes when watched variables change.
Let’s build a simple state / province picker.
var country string
var state string
The country
select will be static, we’ll use this value to recompute the
options and title for the next input.
huh.NewSelect[string]().
Options(huh.NewOptions("United States", "Canada", "Mexico")...).
Value(&country).
Title("Country").
Define your Select
with TitleFunc
and OptionsFunc
and bind them to the
&country
value from the previous field. Whenever the user chooses a different
country, the TitleFunc
and OptionsFunc
will be recomputed.
[!IMPORTANT] We have to pass
&country
as the binding to recompute the function only whencountry
changes, otherwise we will hit the API too often.
huh.NewSelect[string]().
Value(&state).
Height(8).
TitleFunc(func() string {
switch country {
case "United States":
return "State"
case "Canada":
return "Province"
default:
return "Territory"
}
}, &country).
OptionsFunc(func() []huh.Option[string] {
opts := fetchStatesForCountry(country)
return huh.NewOptions(opts...)
}, &country),
Lastly, run the form
with these inputs.
err := form.Run()
if err != nil {
log.Fatal(err)
}
I first wanted to say, thank you for this work and this amazing library!
I was trying this out with a huh.Option[int]
and was unable to get it to work, so I looked at the example which was working and I think I had finally tracked down what was going on for me:
https://github.com/charmbracelet/huh/blob/133f20570e4bebd877228739c5aa1eaf3a75f71b/group.go#L247-L257
It looks like the type switch only has updateOptionsMsg[string]
in the case so other generic types do not match. I added updateOptionsMsg[int]
just to see if it made it work and it seemed to yield the intended behavior. I hacked together something locally with an interface on updateOptionsMsg
so that it could be more generally selected in that type switch, but unsure of the direction you all wanted to go. Happy to submit code or anything like that, if wanted, but also just wanted to make sure I pointed it out if that wasn't the intention to only support the string type of dynamic options.
Thanks again!
@ChrisRx You're absolutely correct! This will definitely be fixed before merging / releasing. Thank you so much, really appreciate the review ❤️
Really excited to see this make it into huh! Do we know when this PR will be merged?
Really excited to see this make it into huh! Do we know when this PR will be merged?
I also want to know, I made the local clone and I'm going to test it on an internal CLI haha