-
Notifications
You must be signed in to change notification settings - Fork 1
Widgets Data
Data widgets display and manipulate structured datasets. Go-gui's data layer is built for production scale: DataGrid virtualises rendering so a million-row table uses the same resources as a ten-row one.
gui.Table(gui.TableCfg{...}) renders a static data table. It is the right choice for
smaller datasets where every row is always visible.
gui.Table(gui.TableCfg{
ID: "results",
Columns: []gui.TableColumnCfg{
{Header: "Name", Field: "name", Width: 200},
{Header: "Score", Field: "score", Width: 80, Align: gui.HAlignRight},
{Header: "Date", Field: "date", Width: 120},
},
Rows: app.TableRows, // []map[string]string
Sizing: gui.FillFit,
})Columns are sortable by default; click a header to toggle ascending/descending order.
w.DataGrid(gui.DataGridCfg{...}) is the high-capability data grid. It virtualises row
rendering — only visible rows are laid out and drawn — so it handles large datasets
without manual tuning.
Feature summary:
- Virtual rows (only visible rows rendered)
- Multi-column sort
- Per-column filters
- Row selection (single or multi)
- Inline cell editing
- Pagination
- Export to CSV, TSV, XLSX, PDF
- Async data sources
w.DataGrid(gui.DataGridCfg{
ID: "orders",
Sizing: gui.FillFill,
Columns: []gui.DataGridColumnCfg{
{
ID: "order_id",
Header: "Order #",
Width: 100,
Sortable: true,
},
{
ID: "customer",
Header: "Customer",
Width: 200,
Sortable: true,
Filter: gui.DataGridFilterText,
},
{
ID: "total",
Header: "Total",
Width: 100,
Align: gui.HAlignRight,
Sortable: true,
},
},
DataSource: app.OrdersDataSource,
OnSelect: func(selectedIDs []string, w *gui.Window) {
gui.State[App](w).SelectedOrders = selectedIDs
},
})Note the factory is w.DataGrid(...) (method on *gui.Window) rather than a
package-level function, because the grid needs access to window services for async
operations.
gui.Tree(gui.TreeCfg{...}) renders a collapsible hierarchical tree. Nodes can carry
icons. The tree supports virtualization for large datasets and simulated lazy loading
(load children on first expand).
gui.Tree(gui.TreeCfg{
ID: "file-tree",
IDFocus: 1,
Sizing: gui.FillFit,
Nodes: []gui.TreeNodeCfg{
{
Text: "src",
Icon: gui.IconFolder,
Nodes: []gui.TreeNodeCfg{
{Text: "main.go", Icon: gui.IconFile},
{Text: "state.go", Icon: gui.IconFile},
},
},
{
Text: "docs",
Icon: gui.IconFolder,
Nodes: []gui.TreeNodeCfg{
{Text: "README.md", Icon: gui.IconFile},
},
},
},
OnSelect: func(id string, _ *gui.Event, w *gui.Window) {
gui.State[App](w).SelectedFile = id
},
})For a virtualized tree that handles thousands of nodes, add IDScroll:
gui.Tree(gui.TreeCfg{
ID: "large-tree",
IDFocus: 2,
IDScroll: 200,
MaxHeight: 400,
Sizing: gui.FillFit,
Nodes: buildLargeTree(),
OnSelect: onSelect,
})See Input Widgets — DatePicker for configuration details.
DatePicker and DatePickerRoller are catalogued in the Data category because they
produce structured time.Time values rather than raw strings.
gui.Form(gui.FormCfg{...}) is a container with built-in validation, submit, and reset
semantics. Fields register sync/async validators via w.FormField(...). The form tracks
touch, dirty, and error state per field and exposes it through three slot callbacks.
gui.Form(gui.FormCfg{
ID: "login-form",
Content: []gui.View{
gui.Input(gui.InputCfg{ID: "email", Placeholder: "Email"}),
gui.Input(gui.InputCfg{ID: "password", Placeholder: "Password", HideText: true}),
gui.Button(gui.ButtonCfg{Text: "Submit", FormSubmit: "login-form"}),
},
OnSubmit: func(e gui.FormSubmitEvent, w *gui.Window) {
// e.Values is a map[string]string of all field values
login(e.Values["email"], e.Values["password"])
},
ErrorSlot: func(fieldID string, issues []gui.FormIssue) gui.View {
return gui.Text(gui.TextCfg{
Text: issues[0].Msg,
TextStyle: gui.CurrentTheme().ColorError.Style(12),
})
},
})Registration of a field validator — typically called once in WindowCfg.OnInit:
w.FormField("login-form", "email", gui.FormFieldCfg{
SyncValidators: []gui.FormSyncValidator{func(ctx gui.FormCtx) []gui.FormIssue {
if !strings.Contains(ctx.Value, "@") {
return []gui.FormIssue{{Code: "invalid_email", Msg: "Enter a valid email"}}
}
return nil
}},
})FormCfg key fields:
| Field | Purpose |
|---|---|
ID |
Required — identifies the form for FormField and FormSubmit
|
Content |
Form fields and action buttons |
OnSubmit |
Called when form is submitted (button with FormSubmit = ID, or Enter) |
OnReset |
Called on reset (button with FormReset = ID) |
ErrorSlot |
Renders errors for a single field — called once per field with issues |
SummarySlot |
Renders a form-level summary (total error count, pending state) |
PendingSlot |
Renders while async validators are running |
ValidateOn |
FormValidateOnChange, FormValidateOnBlur, FormValidateOnSubmit (default: blur+submit) |
AllowInvalidSubmit |
True to permit submission even with validation errors |
AllowPendingSubmit |
True to permit submission during async validation |
NoSubmitOnEnter |
True to disable Enter-to-submit |
Getting Started
Widgets
Layout & Interaction
Visuals
Reference