tablo_core/schema/input.rs
1//! A typed value a form posts under keys no column binds: the [`FormInput`] trait.
2
3use topcoat::context::Cx;
4
5use super::{Field, Schema};
6use crate::values::{FieldError, FormValues};
7
8/// A typed value a form posts under its own keys, which no column binds: what an
9/// [`Action`](crate::Action) asks for before it runs, what a sign-up reads, one item of a
10/// repeater.
11///
12/// Derive it with [`FormInput`](derive@crate::FormInput) on a struct of form scalars, or name
13/// `()` for a value that asks for nothing.
14///
15/// An action with input asks for it before it runs: its button opens the input form in a dialog
16/// over the page, and its submit runs the action with the parsed value. A refused value renders
17/// the form as a page with the field's error, and writes nothing.
18///
19/// A repeater stores its items in a `#[document]` list, so an item is also a `toasty::Embed`
20/// struct. Each row posts the item's keys under its own prefix, and [`write`](Self::write) fills
21/// a stored item's row on the edit page.
22pub trait FormInput: Sized + Send + Sync + 'static {
23 /// The value's controls, each posting its own key. An empty schema asks for nothing: an
24 /// action runs on its button.
25 fn schema() -> Schema;
26
27 /// Parse a submission of [`schema`](Self::schema)'s keys.
28 ///
29 /// # Errors
30 ///
31 /// Every key that failed, each once.
32 fn parse(cx: &Cx, values: &FormValues) -> Result<Self, Vec<FieldError>>;
33
34 /// Write the value's keys as its form posts them: a repeater fills a stored item's row from
35 /// them, and its detail-page column reads them. A password writes nothing, as it never renders
36 /// back into a form. Nothing writes an action's input or a sign-up, so a type used only there
37 /// writes nothing too.
38 fn write(&self, out: &mut FormValues);
39}
40
41/// No input: an action runs on its button.
42impl FormInput for () {
43 fn schema() -> Schema {
44 Schema::empty()
45 }
46
47 fn parse(_cx: &Cx, _values: &FormValues) -> Result<Self, Vec<FieldError>> {
48 Ok(())
49 }
50
51 fn write(&self, _out: &mut FormValues) {}
52}
53
54/// Renders `field`'s control required: the derive marks each field with no blank answer.
55#[doc(hidden)]
56pub fn required_input(field: impl Into<Field>) -> Field {
57 let mut field = field.into();
58 field.set_required(true);
59 field
60}