Form
Form create a form component. The input components in this component will not auto trigger script execution. The user need to submit the form to trigger the script execution.
A form is submitted by its built-in submit button, or by a Button written
inside it: a click inside a form is sent together with the values held since
the last submit, so the run that sees the click is the one that reads the new
values. That is what HideSubmit is for — a search form can offer its own
"Search" button instead of one of those beside a hardwired "Submit".
API
Interface
func Form(c *tgframe.Container, conf ...*FormConf) *tgframe.Container
Parameters
cis Parent container.confis an optional configuration, at most one.
// FormConf is the configuration for the Form component.
type FormConf struct {
tgframe.Base // ID
// SubmitLabel is the text on the built-in submit button. Empty is
// "Submit".
SubmitLabel string
// HideSubmit drops the built-in submit button. Submitting is then up to a
// Button written inside the form; a form with neither has no way to be
// sent.
HideSubmit bool
}
Example
var a, b float64
var ops []int
opItems := []string{"sum", "product"}
tgcomp.Form(p.Main, &tgcomp.FormConf{ID: "form"}).With(func(c *tgframe.Container) {
// No Min or Max, so every number the app user can type is one
// this form accepts: the second return is always true here.
a, _ = tgcomp.Number[float64](c, "a")
b, _ = tgcomp.Number[float64](c, "b")
ops = tgcomp.MultiSelect(c, "ops", opItems,
&tgcomp.MultiSelectConf{Placeholder: "pick the operations"})
})
// Named rather than numbered, so adding an item to opItems cannot
// silently turn into one of the operations already here.
for _, op := range ops {
switch opItems[op] {
case "sum":
tgcomp.Text(p.Main,
fmt.Sprintf("int(a) + int(b) = %d", int(a)+int(b)))
case "product":
tgcomp.Text(p.Main,
fmt.Sprintf("int(a) * int(b) = %d", int(a)*int(b)))
}
}
An untouched field reads as its Default, so the fields hold zero until the
app user fills them in and hits Submit — there is nothing to nil-check.
Submitting from a button inside the form
var keyword string
var searched bool
// No submit button of its own: the Search button inside sends the
// form, so the page offers one button rather than two.
tgcomp.Form(p.Main, &tgcomp.FormConf{
ID: "search_form", HideSubmit: true}).
With(func(c *tgframe.Container) {
keyword = tgcomp.Textbox(c, "keyword")
searched = tgcomp.Button(c, "Search")
// Only a Button sends the form. A download button reports its
// press the same way, and handing someone a file is not
// submitting.
tgcomp.DownloadButton(c, "Save query", []byte("q"),
&tgcomp.DownloadButtonConf{Filename: "query.txt"})
})
if searched {
tgcomp.Text(p.Main, "Searched: "+keyword)
} else {
tgcomp.Text(p.Main, "Not searched yet")
}
searched is true on the run the click was sent with, and keyword already
holds what was typed before it.
Any widget belongs in a form
A slider, a toggle or a checkbox inside a form holds its value like the rest of them, and hands it over on submit rather than on the drag or the click:
var threshold int64
var enabled bool
var notify bool
tgcomp.Form(p.Main, &tgcomp.FormConf{ID: "widget_form"}).
With(func(c *tgframe.Container) {
threshold = tgcomp.Slider(c, "threshold",
(&tcinput.SliderConf[int64]{}).SetMax(100).SetStep(25))
enabled = tgcomp.Toggle(c, "enabled")
notify = tgcomp.Checkbox(c, "notify")
})
tgcomp.Text(p.Main,
fmt.Sprintf("threshold = %d, enabled = %v, notify = %v",
threshold, enabled, notify))
Naming the submit button
var city string
tgcomp.Form(p.Main, &tgcomp.FormConf{
ID: "label_form", SubmitLabel: "Apply"}).
With(func(c *tgframe.Container) {
city = tgcomp.Textbox(c, "city")
})
tgcomp.Text(p.Main, "Applied: "+city)