pub struct ChoiceField<F = ()>(/* private fields */);Expand description
A choice field: Field::choice, or a record form’s choice control (F is the form).
Implementations§
Source§impl<F> ChoiceField<F>
impl<F> ChoiceField<F>
Sourcepub fn options(self, options: impl IntoOptions) -> Self
pub fn options(self, options: impl IntoOptions) -> Self
Static options: values that are their own label
(["draft", "published"]), (value, label) pairs whose label is a string or a
Text ([("draft", text!("status-draft"))]), or a
#[derive(Options)] enum’s
options().
Sourcepub fn multiple(self) -> Self
pub fn multiple(self) -> Self
Takes several options: a checkbox per option, posting the field’s key once per checked
box. A record form’s many-to-many field (Vec<K> with #[form(relationship = R)]) is one;
parse_list reads one in an action’s input.
It offers at most MAX_RELATIONSHIP_OPTIONS
records: past them it lists none but the chosen ones, and refuses a submission choosing
another. A record form’s edit re-checks only the keys the record does not link yet.
searchable filters the listed options as the user types. A condition cannot watch it,
it cannot depend on another field, and its default is a list.
Sourcepub fn radio(self) -> Self
pub fn radio(self) -> Self
Renders a radio per option rather than a <select>, so every option shows without a
click: for a few options, such as a status or a visibility. A multiple
choice keeps its checkboxes.
The options load as a select’s do, and past the option cap only the chosen one lists.
searchable filters the listed options as the user types. A radio
choice cannot depend on another field, since the browser lists its
options once, but another choice can depend on it.
Field::choice(lens!(Post.visibility))
.options(vec![
("public".to_string(), "Public".to_string()),
("private".to_string(), "Private".to_string()),
])
.radio();Sourcepub fn min_items(self, count: usize) -> Self
pub fn min_items(self, count: usize) -> Self
Refuse a submission choosing fewer than count options. A multiple
choice’s blank answer is the empty list, which no other rule refuses, so min_items(1) is
how one requires a choice. Only the server checks it. A choice that is not multiple fails
the mount, as does a minimum above max_items or above the count of static options.
Sourcepub fn max_items(self, count: usize) -> Self
pub fn max_items(self, count: usize) -> Self
Refuse a submission choosing more than count options; min_items
says which choices take it.
Sourcepub fn searchable(self) -> Self
pub fn searchable(self) -> Self
Filters options as the user types, fetching from the relationship past the option cap.
Sourcepub fn relationship<R>(self) -> Selfwhere
R: OptionSource + 'static,
pub fn relationship<R>(self) -> Selfwhere
R: OptionSource + 'static,
Loads options from a related source’s tenant-scoped query, each valued by its primary key
and labelled by the source’s label, degrading to type-to-search
past the option cap.
A resource’s options carry its record_title, the
title its detail page shows. relationship_labelled
labels one field’s options otherwise.
- Options come from the related resource’s tenant-scoped query and follow its policy: the
list is empty and the field shows “not available” unless the related resource’s policy
allows
ViewAny, and each record must pass itsView. - A submitted key must be one of those records, so a hand-crafted POST cannot point at another tenant’s row. The write checks the key again inside its transaction, so a record deleted, moved to another tenant or hidden since the form validated refuses the write with the same field error.
- At most 200 options load. Past that, a
.searchable()choice turns into type-to-search againstGET {list_url}/-/options, which searches the related table’ssearchable()columns; a non-searchable choice shows an error instead..searchable()also filters a short list as you type. Without JavaScript the plain select remains.
Sourcepub fn depends_on<M, T>(
self,
parent: &impl Watched<F>,
column: impl Into<Path<M, T>>,
) -> Self
pub fn depends_on<M, T>( self, parent: &impl Watched<F>, column: impl Into<Path<M, T>>, ) -> Self
Offers only the related rows whose column column equals the value parent posts: the
cities of the chosen country. The browser fetches the options again when parent changes,
and a submission must name a row of the posted parent value. A blank parent offers none.
column belongs to the relationship’s source model; mounting
refuses another model, a choice without a relationship, and a parent the schema does not
place.
- The form renders the options of the parent’s current value, and none while it is blank.
When the parent changes, the browser fetches the new options from
GET {list_url}/-/optionsand keeps the current choice only if they still offer it. A choice they drop changes too, so a choice depending on it, or a condition watching it, follows. - A submission must name a record of the parent value it posts, or, on an edit that does not post the parent, of its stored value. The write checks the key again inside its transaction, as for any relationship.
- The 200-option cap counts the parent’s records. Past it, a
.searchable()dependent choice searches among them, and any other offers no option. A failed fetch offers none either. - Without JavaScript the options stay those of the value the page rendered with, and a submission naming another value’s record is refused.
columnmust belong to the relationship’s model, and the parent must be placed in the same schema: mounting refuses either mistake. Only a resource’s form serves the options, so mounting also refuses a dependent choice in an action’s input.- A multiple choice neither depends on another field nor narrows one: mounting refuses both.
Sourcepub fn relationship_labelled<R>(
self,
label: impl Fn(&R::Model) -> String + Send + Sync + 'static,
) -> Selfwhere
R: OptionSource + 'static,
pub fn relationship_labelled<R>(
self,
label: impl Fn(&R::Model) -> String + Send + Sync + 'static,
) -> Selfwhere
R: OptionSource + 'static,
Loads options as relationship does, labelling each by label
instead of the source’s label: to tell apart records that share a title. The option’s
record loads without its relations.
Source§impl<F> ChoiceField<F>
impl<F> ChoiceField<F>
Sourcepub fn default(self, value: impl IntoFormValue) -> Self
pub fn default(self, value: impl IntoFormValue) -> Self
Fills the create form’s control with value: any
FormScalar or a &str in the form spelling, or, for a
multiple choice, an array or Vec of them. On a
disabled field it is the value a create stores. A schema
refuses a default the control never posts: one a typed field does not parse, one
not among a choice’s options, a list on a control posting one value, and one value
on a multiple choice.
Field::choice(Post::fields().status())
.options(["draft", "published"])
.default("draft");
Field::text(Post::fields().views()).default(0_i64).disabled();
Field::choice_input("channels")
.options(["email", "sms"])
.multiple()
.default(["email"]);- The control names its help text in
aria-describedby, beside its error. - A disabled control renders
disabled, so the browser posts nothing for it, and the panel drops a key posted anyway, with a file field’s carried upload. An edit keeps the stored value. A create stores the field’s default, else its blank answer:.disabled()on a field with neither refuses to mount, since no create could fill it. .disabled_on_edit()leaves the create form’s control enabled: the create sets the value, and no edit changes it.- A condition watching a disabled field reads what the browser shows: its default on a create, its stored value on an edit, never what the submission posts.
- A default seeds the create form and an action’s input form; an edit form shows the stored value. The blank answer is different: it is what an empty submission stores. Mounting refuses a default the control never posts: one a typed field does not parse, or not one of a choice’s options.
- A repeater’s row controls take neither
disablednordefault: mounting refuses both.
Source§impl<F> ChoiceField<F>
impl<F> ChoiceField<F>
pub fn label(self, label: impl Into<Text>) -> Self
pub fn name(&self) -> &str
Sourcepub fn visible_when(
self,
watched: &impl Watched<F>,
values: impl IntoIterator<Item = impl Into<String>>,
) -> Self
pub fn visible_when( self, watched: &impl Watched<F>, values: impl IntoIterator<Item = impl Into<String>>, ) -> Self
Shows the field only while watched posts one of values: an option’s value, or
true for a checked toggle. A hidden field posts nothing, so an edit keeps its
stored value and a create takes its blank answer; a field with no blank answer
cannot be conditional. A field shows under one condition: a later call replaces an
earlier one, so a field depending on two watched fields sits in a
Section guarded by the other.
let kind = Field::choice(Customer::fields().kind()).options(["person", "company"]);
let vat = Field::text(Customer::fields().vat_number()).visible_when(&kind, ["company"]);
Schema::new((kind, vat));- The browser shows and hides the field as the watched one changes, with no request. A hidden field’s control is disabled, so the browser neither validates nor posts it. Without JavaScript, the fields start as the stored values show them and stay that way.
- The panel reads a submission the same way and drops a hidden field’s posted key, and a file field’s carried upload: an edit keeps the stored value, and a create stores the blank answer. A conditional field therefore needs a blank answer, and mounting refuses one without.
- Mounting also refuses a value the watched field never posts (a choice’s option or
a toggle’s
trueandfalseare checked), and a condition watching a field that another condition hides while the guarded field still shows: place the guarded field inside the block that hides the watched one. A schema also refuses a condition watching a field it does not place, which only a page’s or an action’s schema can do: a resource’s form places every record-form field. - A toggle is followed through its checkbox. An app’s own checkbox
Controlposts the samevaluechecked or not, so a condition cannot follow it. - A multiple choice’s key holds a list, which no condition value spells: mounting refuses a condition watching one.
Source§impl<F> ChoiceField<F>
impl<F> ChoiceField<F>
Sourcepub fn help(self, text: impl Into<Text>) -> Self
pub fn help(self, text: impl Into<Text>) -> Self
Renders text under the control, which the control names as its description.
Sourcepub fn disabled(self) -> Self
pub fn disabled(self) -> Self
Renders the control disabled on the create and edit forms. The server drops a
value posted for it anyway, so an edit keeps the stored value and a create takes
the field’s default, else its blank answer; a field with neither cannot be
created, and its panel refuses to mount.
Sourcepub fn disabled_on_edit(self) -> Self
pub fn disabled_on_edit(self) -> Self
Renders the control disabled on the edit form only: the create form sets the value, and no edit changes it.
Sourcepub fn custom(self, control: impl Control + 'static) -> CustomField<F>
pub fn custom(self, control: impl Control + 'static) -> CustomField<F>
Renders the field with an app’s Control instead, as Field::custom does:
how a record form’s control takes a custom input. The field keeps its key and
label; the replaced control’s own modifiers, such as email, unique or
options, are dropped with it.