Aria 2.0.0
C++23 MVVM framework (C++20 minimum) — reactive, coroutine-first, ABI-layered
Loading...
Searching...
No Matches
Recipe 1 — Form with sync + async rules

Goal: a login/signup field that validates synchronously (non-empty, length, format) and also runs an asynchronous rule (e.g. "username available?") without blocking the UI.

See also: docs/guide/validation.md, docs/reference/error-model.md, and the validation contract V-N in the headers.

Synchronous rules

FormValidator::rule(predicate, message, rule_id) attaches a predicate that runs on every change of the bound Property. A failing rule surfaces its message under the given rule_id.

#include "aria/binding/form.hpp" // aria::FormValidator
aria::FormValidator form;
form.rule([&]{ return !username.get().empty(); },
"Username is required", "required");
form.rule([&]{ return username.get().size() >= 3; },
"At least 3 characters", "min_len");
// The aggregate validity is observable (a Property<bool> member, not a
// method); bind it to a submit button.
auto sub = form.is_valid.on_changed([](bool ok){ submit_button.enabled = ok; });
// Likewise: form.is_dirty, form.is_pending, form.first_error.
Definition property.hpp:103
T get() const
Auto-tracked read.
Definition property.hpp:138
::aria::Subscription on_changed(std::function< void(const T &)> fn)
Run fn(new_value) every time the value changes.
Definition property.hpp:200

Asynchronous rule

aria::async::AsyncValidator<T> runs a coroutine rule on a worker executor and writes the pending/valid/invalid state back on the UI executor. Its factory has the signature std::function<Task<AsyncRuleResult>(T value, CancellationToken tok)> (see aria/async/async_validator.hpp for AsyncRuleResult). It attaches to a sync aria::Validator<T> plus its source aria::Property<T>:

aria::Validator<std::string> username_validator; // the sync validator the field uses
ui_executor, net_pool,
[](std::string name, aria::CancellationToken tok)
co_return co_await api::check_username_free(std::move(name), tok);
}};
// `attach_to` returns a Subscription that owns the wiring; dropping it
// detaches AND cancels any in-flight rule (V-6).
auto async_sub = uniqueness.attach_to(username_validator, username);
Definition validator.hpp:135
Driver that turns a coroutine factory into a latest-wins async validation rule attached to a Validato...
Definition async_validator.hpp:210
::aria::Subscription attach_to(::aria::Validator< T > &v, ::aria::Property< T > &source)
Attach to a Validator + its source Property.
Definition async_validator.hpp:237
Definition task.hpp:78

Why this is safe

  • No torn state. The async rule cancels the previous in-flight run on every new keystroke and mints a fresh CancellationSource (V-1), so a slow earlier request can never overwrite a newer result.
  • Pending is observable. attach_to immediately fires begin_pending() (V-2), so the UI can show a spinner while the network rule resolves.
  • Lifetime is RAII. Destroying the returned Subscription cancels the in-flight rule and detaches (V-6) — no callback fires against a dead form.