huh icon indicating copy to clipboard operation
huh copied to clipboard

Dynamic Forms

Open tetienne opened this issue 1 year ago • 11 comments

Is your feature request related to a problem? Please describe. My current CLI ask several questions to the end user, and each question depends on the choice of the previous one. For instance, select an AWS cluster, then an AWS service. So I cannot use the form feature of huh (or can I?). Because of this, I cannot display the help message for my prompt.

Describe the solution you'd like Add a parameter ShowHelpMessage for the fields also.

Describe alternatives you've considered Create a form for each single question.

Additional context N/A

tetienne avatar Dec 18 '23 11:12 tetienne

Hi! This is something we'd to explore in a more official capacity, but for now you can achieve a similar effect using multiple forms. For an example to help get started see https://github.com/charmbracelet/huh/pull/75.

meowgorithm avatar Dec 19 '23 15:12 meowgorithm

Thx for the exemple. So no magic yet here :)

tetienne avatar Dec 20 '23 07:12 tetienne

+1 to this enhancement!!

alinagard avatar Dec 21 '23 19:12 alinagard

You can may be use WithHideFunc to conditionally show some questions. Here is the rewriten example of #75 (with corrected "Carrot" option for "vegetables" 🙂).

package main

import (
	"fmt"

	"github.com/charmbracelet/huh"
)

func main() {

	var (
		category string
		choice   string
	)

	huh.NewForm(
		huh.NewGroup(
			huh.NewSelect[string]().
				Title("What are you in the mood for?").
				Value(&category).
				Options(
					huh.NewOption("Some fruit", "fruits"),
					huh.NewOption("A vegetable", "vegetables"),
					huh.NewOption("A drink", "drinks"),
				),
		),
		huh.NewGroup(
			huh.NewSelect[string]().
				Title("Okay, what kind of fruits are you in the mood for?").
				Value(&choice).
				Options(
					huh.NewOption("Tangerine", "tangerine"),
					huh.NewOption("Canteloupe", "canteloupe"),
					huh.NewOption("Pomelo", "pomelo"),
					huh.NewOption("Grapefruit", "grapefruit"),
				),
		).WithHideFunc(func() bool {
			return category != "fruits"
		}),
		huh.NewGroup(
			huh.NewSelect[string]().
				Title("Okay, what kind of vegetables are you in the mood for?").
				Value(&choice).
				Options(
					huh.NewOption("Carrot", "carrot"),
					huh.NewOption("Jicama", "jicama"),
					huh.NewOption("Kohlrabi", "kohlrabi"),
					huh.NewOption("Fennel", "fennel"),
					huh.NewOption("Ginger", "ginger"),
				),
		).WithHideFunc(func() bool {
			return category != "vegetables"
		}),
		huh.NewGroup(
			huh.NewSelect[string]().
				Title("Okay, what kind of drinks are you in the mood for?").
				Value(&choice).
				Options(
					huh.NewOption("Coffee", "coffee"),
					huh.NewOption("Tea", "tea"),
					huh.NewOption("Bubble Tea", "bubble-tea"),
					huh.NewOption("Agua Fresca", "agua-fresca"),
				),
		).WithHideFunc(func() bool {
			return category != "drinks"
		}),
	).Run()

	fmt.Printf("One %s coming right up!\n", choice)
}

kpym avatar Jan 07 '24 20:01 kpym

I would like to extend this request to include external updates such as API calls. I mentioned some details here https://github.com/charmbracelet/huh/issues/183

iloveicedgreentea avatar Apr 10 '24 18:04 iloveicedgreentea

Yep, that's definitely something we'll need to support, which also means we'll probably need a spinner if the func that computes the data runs over a certain time threshold.

meowgorithm avatar Apr 11 '24 14:04 meowgorithm

Just a heads up we're making good progress on dynamic forms. It looks like the API will be mostly allowing any option Title, Description, Option to be "Func"-able, i.e. take a function to populate the field from. It will automatically cache the options if desired as well.

https://github.com/charmbracelet/huh/assets/42545625/cdff62f1-a3aa-4a19-93f0-d002b96bbe2d

maaslalani avatar May 01 '24 15:05 maaslalani

Awesome really looking forward to it. I really enjoy working with Huh, it has been great and everyone has been super impressed of the things we used it for

iloveicedgreentea avatar May 01 '24 16:05 iloveicedgreentea

Hello, I’d like to have a group where I can dynamically add/remove input fields with key bindings (like pressing n to add a field and pressing d to remove the current field). Will the work on this issue cover this use case or is it something completely unrelated?

yann-soubeyrand avatar May 16 '24 21:05 yann-soubeyrand

I am aware of the example on conditional form but is there any way to populate the options in a group conditionally as well? @maaslalani

nilansaha avatar Jun 07 '24 01:06 nilansaha

Dynamics work fine, but since WithHidefunc only works for groups, there is kind of an interruption in the user experience. I personally would like to have an overview about all my decisions made through the order process, but once a new group appears on screen, the history is lost. Is there any way around, so that all previous decisions are still visible –~and could even be reverted later on~?

Edit: So to say a "WithHideFunc" per "NewSelect" would be great.

neilyoung avatar Sep 30 '24 20:09 neilyoung