pub struct Field<'a> {
pub kind: FieldKind,
pub name: &'a str,
pub label: &'a str,
pub hint: Option<&'a str>,
pub error: Option<&'a str>,
pub placeholder: Option<&'a str>,
pub options: &'a [Choice<'a>],
pub required: bool,
pub extended: bool,
}Expand description
One field of a form.
Borrowed rather than owned: a description is built, read once by a renderer, and dropped. Nothing here outlives the screen it describes.
§What it carries, and what it does not
Stated here so the next renderer does not re-ask, which is what the first two both did. It carries everything a renderer needs to draw the field: its kind, what it is called, what it is asked for, its standing help, what is wrong with it now, whether it is compulsory, whether it hides behind a disclosure, its ghost text, and the options it offers.
It does not carry the current value, and it is not going to. That is the
one thing here that is genuinely renderer state: a webview reads it back out
of the DOM, an immediate-mode renderer holds a &mut to the app’s own field
and writes through it, and a terminal keeps an edit buffer. A description
that carried the value would have to carry a way to write it back, at which
point it is a form model and no longer a description.
Validation is absent for the reason FieldKind records: error is
the result of validating, supplied by whoever validated. Nothing here
decides that a value is wrong.
Fields§
§kind: FieldKindWhat kind of value it takes.
name: &'a strThe name the value is submitted under.
label: &'a strWhat the user is asked for.
hint: Option<&'a str>Standing help, shown whether or not anything is wrong.
error: Option<&'a str>What is currently wrong with the value.
placeholder: Option<&'a str>Ghost text shown while the field is empty.
User-facing text, and it sits with label and hint rather than with
the value because it is a property of the question and not of the
answer. It lived renderer-side in makeover-webview until 0.8.0 for one
reason and it was not a reading on where it belonged: adding a field to
a published struct is a breaking change.
Not a substitute for a label. A field labelled only by its placeholder loses its label the moment anything is typed, and no renderer here can make that not happen, so the description keeps both.
options: &'a [Choice<'a>]The options offered, in the order they are offered.
Empty for every kind FieldKind::offers_options rejects. A field
described with no options is sayable on purpose: it is what an app with
an unfinished-loading option list actually has, and a renderer showing
an empty control says so on screen rather than in a log.
Which option is current is not here. That is the value, and the value is renderer state.
required: boolWhether the form refuses to submit without it.
extended: boolWhether the field lives behind a “more options” disclosure.
Implementations§
Source§impl<'a> Field<'a>
impl<'a> Field<'a>
Sourcepub const fn new(kind: FieldKind, name: &'a str, label: &'a str) -> Self
pub const fn new(kind: FieldKind, name: &'a str, label: &'a str) -> Self
A plain required-nothing field of the given kind.
Sourcepub const fn select(
name: &'a str,
label: &'a str,
options: &'a [Choice<'a>],
) -> Self
pub const fn select( name: &'a str, label: &'a str, options: &'a [Choice<'a>], ) -> Self
A select offering the given options.
One of the two kinds under-described by Field::new, so it gets a
constructor rather than leaving every call site to remember that a
select with an empty options renders as an empty select.
Sourcepub const fn radio(
name: &'a str,
label: &'a str,
options: &'a [Choice<'a>],
) -> Self
pub const fn radio( name: &'a str, label: &'a str, options: &'a [Choice<'a>], ) -> Self
A radio group offering the given options.
The other. Same hazard as select and a worse one: a
radio group with no options draws nothing at all, so a call site that
forgot them has an empty rectangle rather than a visibly empty control.
Sourcepub const fn invalid(&self) -> bool
pub const fn invalid(&self) -> bool
Whether the field is currently reporting a problem.
Read this rather than testing error.is_some() at each renderer: the
error state has to mark the field’s whole group and not only the
message, because a renderer with no descendant selectors (egui, a
terminal) cannot find the group from the message. goingson already marks
the group and Balanced Breakfast does not, so goingson’s shape is the
one taken here.