Skip to content
Custom and form dialogs

Custom and form dialogs

Your own content

dialog.ShowCustom shows any canvas object with a title and one button that closes the dialog. You choose the button’s label. The dialog starts at the minimum size of the content you pass.

custom := widget.NewButton("Custom content", func() {
	content := container.NewVBox(
		widget.NewLabel("Any canvas object can be the body."),
		widget.NewCheck("Show this again", nil),
	)
	dialog.ShowCustom("Tip of the day", "Close", content, w)
})

Content with confirm and cancel

dialog.ShowCustomConfirm adds a second button. The callback gets true for the confirm button and false for the cancel button or any other way of closing. Read the values from your widgets inside the callback.

rename := widget.NewButton("Rename…", func() {
	name := widget.NewEntry()
	name.SetPlaceHolder("New name")
	dialog.ShowCustomConfirm("Rename", "Rename", "Cancel", name,
		func(ok bool) {
			if ok {
				status.SetText("Renamed to " + name.Text)
			}
		}, w)
})

NewCustomConfirm returns a ConfirmDialog, the same type the yes/no dialog uses, so SetConfirmImportance and the other methods work here too.

Your own buttons

dialog.NewCustomWithoutButtons creates a dialog with an empty button row. SetButtons then fills it with whatever you like, laid out in one row. Your buttons do not close the dialog by themselves, so call Hide() from their handlers.

choose := widget.NewButton("Own buttons", func() {
	var d *dialog.CustomDialog
	pick := func(size string) func() {
		return func() {
			status.SetText("Size: " + size)
			d.Hide()
		}
	}
	d = dialog.NewCustomWithoutButtons("Pick a size",
		widget.NewLabel("Which size do you want?"), w)
	d.SetButtons([]core.CanvasObject{
		widget.NewButton("Small", pick("small")),
		widget.NewButton("Medium", pick("medium")),
		widget.NewButton("Large", pick("large")),
	})
	d.Show()
})

CustomDialog also has SetIcon, which shows an icon in the dialog’s top corner. Pass nil to remove it.

Forms

dialog.ShowForm lays out a list of widget.FormItem values as a form, with confirm and cancel buttons under it.

signUp := widget.NewButton("Sign up…", func() {
	email := widget.NewEntry()
	email.Validator = func(s string) error {
		if !strings.Contains(s, "@") {
			return errors.New("enter an email address")
		}
		return nil
	}
	password := widget.NewPasswordEntry()

	items := []*widget.FormItem{
		widget.NewFormItem("Email", email),
		widget.NewFormItem("Password", password),
	}
	dialog.ShowForm("Create account", "Sign up", "Cancel", items,
		func(ok bool) {
			if ok {
				status.SetText("Signed up as " + email.Text)
			}
		}, w)
})

The form dialog ties into validation. If any field has a validator (here the email entry’s Validator) and its value fails, the confirm button is disabled. The button’s state is checked when the dialog is built and again whenever a field’s validation result changes. So the callback only ever gets true with valid values. To submit from code, call Submit on the dialog that NewForm returns; it does nothing while the confirm button is disabled.

For more on validators and forms, see Forms.

The complete example

// Custom dialogs and form dialogs.
package main

import (
	"errors"
	"strings"

	"github.com/belluikit/bellui"
	"github.com/belluikit/bellui/app"
	"github.com/belluikit/bellui/container"
	"github.com/belluikit/bellui/core"
	"github.com/belluikit/bellui/dialog"
	"github.com/belluikit/bellui/widget"
)

func main() {
	a := app.New()
	w := a.NewWindow("Custom dialogs")
	status := widget.NewLabel("")

	custom := widget.NewButton("Custom content", func() {
		content := container.NewVBox(
			widget.NewLabel("Any canvas object can be the body."),
			widget.NewCheck("Show this again", nil),
		)
		dialog.ShowCustom("Tip of the day", "Close", content, w)
	})

	rename := widget.NewButton("Rename…", func() {
		name := widget.NewEntry()
		name.SetPlaceHolder("New name")
		dialog.ShowCustomConfirm("Rename", "Rename", "Cancel", name,
			func(ok bool) {
				if ok {
					status.SetText("Renamed to " + name.Text)
				}
			}, w)
	})

	choose := widget.NewButton("Own buttons", func() {
		var d *dialog.CustomDialog
		pick := func(size string) func() {
			return func() {
				status.SetText("Size: " + size)
				d.Hide()
			}
		}
		d = dialog.NewCustomWithoutButtons("Pick a size",
			widget.NewLabel("Which size do you want?"), w)
		d.SetButtons([]core.CanvasObject{
			widget.NewButton("Small", pick("small")),
			widget.NewButton("Medium", pick("medium")),
			widget.NewButton("Large", pick("large")),
		})
		d.Show()
	})

	signUp := widget.NewButton("Sign up…", func() {
		email := widget.NewEntry()
		email.Validator = func(s string) error {
			if !strings.Contains(s, "@") {
				return errors.New("enter an email address")
			}
			return nil
		}
		password := widget.NewPasswordEntry()

		items := []*widget.FormItem{
			widget.NewFormItem("Email", email),
			widget.NewFormItem("Password", password),
		}
		dialog.ShowForm("Create account", "Sign up", "Cancel", items,
			func(ok bool) {
				if ok {
					status.SetText("Signed up as " + email.Text)
				}
			}, w)
	})

	w.SetContent(container.NewVBox(custom, rename, choose, signUp, status))
	bellui.ShowAndRun(w)
}