Virtual Fields
A virtual field is a purely input field whose value may or may not be provided at creation, used to trigger a change in one or more fields that depend on it.
- It must have one or more dependent fields depending on it.
- It must have a validator.
- It may also have a re-validator.
- It may have an
alias- a different field name on the input struct, used in place of the actual field name (only allowed if the corresponding output field is a dependent field that directly depends on this virtual field). - It may have a sanitizer.
- It may leverage
ignore,ignore_initandignore_updateprovision rules. - It may have
on_failureandon_successevent handlers.
Example
virtual_field is a virtual input field. The output dependent uses its value when provided,
otherwise it falls back to a default. The dependent field declares its dependency with
.depends_on(...):
use std::{future::ready, sync::LazyLock};
use ivo::{dependent_field, virtual_field, IvoContext, IvoInputStruct, IvoModel, IvoStruct};
const DEFAULT_DEPENDENT: &str = "DEFAULT_DEPENDENT_VALUE";
type Ctx = IvoContext<DataInput, Data>;
#[derive(Clone, Debug, PartialEq, IvoInputStruct)]
struct DataInput {
pub virtual_field: String,
}
#[derive(Debug, Clone, PartialEq, IvoStruct)]
struct Data {
pub dependent: String,
}
static MODEL: LazyLock<IvoModel<DataInput, Data>> = LazyLock::new(|| {
IvoModel::new(
|f| {
f.field(virtual_field("virtual_field").validate(|v: String, _, _| ready(Ok(Some(v)))))
.field(
dependent_field("dependent")
.default(DEFAULT_DEPENDENT.to_string())
.depends_on(["virtual_field"])
.resolve(|ctx: Ctx, _| {
ready(
ctx.input()
.virtual_field
.clone()
.unwrap_or_else(|| ctx.values().dependent.clone()),
)
}),
)
},
|o| o,
)
});