Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Display ¶ added in v0.4.0
Display is what a changelist cell shows. Text is always HTML-escaped. Href, when set, makes the cell a link, but only if it is a relative URL or an absolute http or https URL; any other value falls back to plain text.
type DisplayFunc ¶ added in v0.4.0
DisplayFunc computes one changelist cell from a model row. The row is passed as a pointer to the model value (for example *Upload), so the function can read any of its fields, including ones that are not shown as columns. A panic in the function is the host's bug: admin does not recover it.
type FieldContext ¶
type FieldContext struct {
// Name is the model field's Go name — also the base name a simple
// widget reads directly from the submitted form, and the stable prefix
// a multi-input widget derives its own input names from.
Name string
// Label is the field's display label (from Options.Labels, or a
// humanized default).
Label string
// HelpText is optional descriptive text for the field (from
// Options.HelpText); empty if unset.
HelpText string
// Value is the field's current value, formatted for display. Empty for
// a new (zero) instance.
Value string
// MaxLength is the field's declared maximum length in characters (a
// tango:"varchar=n" string), or 0 when the field is unbounded. The
// built-in input renders it as the maxlength attribute; the server stays
// the authority, since browsers count in UTF-16 units.
MaxLength int
// Checked is the field's current boolean value, for checkbox-shaped
// widgets.
Checked bool
// ReadOnly reports whether the field should render non-editably and
// ignore submitted form data entirely (Options.ReadOnly). A Widget set
// via Options.Widgets is never consulted for a ReadOnly field — the
// admin package renders a single generic read-only presentation
// instead, uniformly, regardless of which Widget the field would
// otherwise use.
ReadOnly bool
// SelectOptions lists every row of the related model as a value/label
// pair, populated only for a foreign key field whose related model is
// registered — nil otherwise.
SelectOptions []SelectOption
// RelatedCreateURL links to the related model's admin create page for
// foreign-key fields whose related model is also admin-registered.
// Empty means no quick-create affordance should render.
RelatedCreateURL string
// PreviewURL is the absolute admin URL a preview widget posts its text
// to; empty for a widget that is not a PreviewWidget.
PreviewURL string
// RelatedCreateLabel is the accessible label for RelatedCreateURL.
// Empty means widgets may fall back to their own default.
RelatedCreateLabel string
// Error is the message the form shows beside this field after a failed
// save, or empty when the field has no error. The built-in widgets mark
// their control aria-invalid when it is set; a custom widget may do the
// same.
Error string
}
FieldContext carries what a Widget needs to render and parse one model field's create/edit form control. The same FieldContext is passed to both Render and Parse, so a widget can derive its own submitted form key(s) from Name identically on both sides — e.g. a multi-input widget might use Name+"_date" and Name+"_time" — rather than a render-time and parse-time convention drifting apart.
func (FieldContext) DescribedBy ¶ added in v0.4.0
func (f FieldContext) DescribedBy() string
DescribedBy returns the value for the control's aria-describedby: the ids of the field's help text and error element, in that order, separated by a space. It is empty when the field has neither.
type FieldValues ¶
FieldValues is the whole submitted form, so a Widget's Parse can read more than one input for a single Go field (see FieldContext.Name).
type ModelRegistration ¶
ModelRegistration is the admin metadata for a registered model.
type Options ¶
type Options struct {
ListDisplay []string
// SingularName and PluralName name one row and several rows in messages
// and confirmations, such as "Delete this book" and "3 books deleted".
// Unset, each falls back to the humanized Go type name.
SingularName string
PluralName string
// Display computes changelist cells, keyed by a name in ListDisplay: a
// registered field (overriding its value) or a synthetic column, which
// needs a Labels entry for its header. See DisplayFunc.
Display map[string]DisplayFunc
Search []string
Ordering []string
// Label names one of this model's own fields to display whenever it is
// shown as a related object elsewhere (e.g. on a Post's admin page for
// a Post.AuthorID foreign key). Unset falls back to showing the raw
// primary key value — never a hard error.
Label string
// Labels overrides a field's humanized default display label, keyed by
// Go field name.
Labels map[string]string
// HelpText adds descriptive text below a field's form control, keyed by
// Go field name.
HelpText map[string]string
// ReadOnly lists fields that render non-editably in create/edit forms.
// On edit, a read-only field keeps its existing stored value regardless
// of submitted form data; on create, it stays at its Go zero value.
// Submitted data for a read-only field is always ignored, never parsed.
ReadOnly []string
// FieldOrder lists fields in the order they should render; fields not
// listed keep their existing default order after the ordered ones.
FieldOrder []string
// Widgets overrides how a field renders and parses in create/edit
// forms, keyed by Go field name. See Widget — best-effort, not a
// stable contract.
Widgets map[string]Widget
// Filters lists boolean and foreign key fields the changelist can be
// filtered by, in the order they appear above the list.
Filters []string
// BulkDelete lets a staff account delete the rows checked on one
// changelist page, after a confirmation, in one all-or-nothing
// transaction. Rows that reference a deleted row are deleted with it,
// exactly as in a single-row delete. Off by default; it needs JavaScript
// in the browser and never spans more than one page of rows.
BulkDelete bool
}
Options controls how a model appears in the admin.
type PreviewWidget ¶ added in v0.4.0
PreviewWidget is the optional extension a Widget implements when its field can show a preview of the submitted text. Only the Markdown widget uses it today. Admin owns the preview route: it calls Preview for the one derived, staff-only endpoint of a preview field and wraps the result, so a widget cannot register a route. Preview receives a context derived from the request's and must not persist anything; the caller applies the deadline and output limits.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry stores admin registrations by model name.
func NewRegistry ¶
NewRegistry returns an empty, ready-to-use admin Registry.
func (*Registry) Get ¶
func (r *Registry) Get(name string) (ModelRegistration, bool)
Get returns an admin registration by model name.
func (*Registry) Registrations ¶
func (r *Registry) Registrations() []ModelRegistration
Registrations returns every registered model in unspecified order.
type SelectOption ¶
SelectOption is one <option> in a foreign key field's <select>.
type Widget ¶
type Widget interface {
Render(ctx context.Context, f FieldContext) template.HTML
Parse(ctx context.Context, f FieldContext, form FieldValues, dest reflect.Value) error
}
Widget renders one model field's create/edit form control and parses its submitted value back into the Go field, replacing tanGO's default behavior for that field alone — nothing else about the form changes. ctx is the request's context: a widget translates its own messages with i18n.T(ctx, key, fallback), so a host catalog can word them. tanGO's built-in field behaviors (a generic text/number/date-time input, a checkbox, a textarea, and the foreign-key select) are themselves Widgets, set via Options.Widgets like any custom one.
This interface, the built-in widgets other than JSON and Markdown, and Options' Widgets/Labels/HelpText/ReadOnly/FieldOrder fields are best-effort, not a stable contract; see docs/compatibility.md. A widget's Render output may include its own <link>/<script> tags for CSS/JS (served via its owning app's own embed.FS route, per the convention reusable apps already use for static assets); since there is no shared deduplication, that output must be idempotent — safe to emit once per rendered instance — because the same widget on multiple fields will render its tags more than once.