31template<PropertyValue T>
51 initial_(
value.get()) {
55 [[nodiscard]]
const std::string&
field_path() const noexcept {
60 std::string rule_id_value = {}) {
61 validator.rule(std::move(r), std::move(rule_id_value));
65 template<std::predicate<const T&> P>
67 std::string rule_id_value = {}) {
68 validator.must(std::forward<P>(predicate),
70 std::move(rule_id_value));
75 requires requires(
const T& v) { { v.empty() } -> std::convertible_to<bool>; }
77 return must([](
const T& v) {
return !v.empty(); },
83 requires requires(
const T& v) { { v.size() } -> std::convertible_to<std::size_t>; }
85 return must([n](
const T& v) {
return v.size() >= n; },
111 dirty = !(v == initial_);
116 SubscriptionBag bag_;
124 template<
typename Field>
126 fields_.push_back(FieldHooks{
127 [&f] {
return f.is_valid.get(); },
128 [&f] {
return f.dirty.get(); }
130 bag_ += f.is_valid.on_changed([
this](
bool) { recompute_(); });
131 bag_ += f.dirty.on_changed([
this](
bool) { recompute_(); });
144 std::function<bool()> valid;
145 std::function<bool()> dirty;
149 bool all_valid =
true;
150 bool any_dirty =
false;
151 for (
auto& f : fields_) {
152 all_valid = all_valid && f.valid();
153 any_dirty = any_dirty || f.dirty();
159 std::vector<FieldHooks> fields_;
160 SubscriptionBag bag_;
181 template<
typename Field>
183 auto pending = [&f] {
184 if constexpr (
requires { f.validator.state(); })
return f.validator.state().get().pending;
187 fields_.push_back(FieldHooks{
188 [&f] {
return f.is_valid.get(); },
189 [&f] {
return f.dirty.get(); },
191 [&f] {
return f.error_full.get(); },
194 bag_ += f.is_valid.on_changed ([
this](
bool) { recompute_(); });
195 bag_ += f.dirty.on_changed ([
this](
bool) { recompute_(); });
196 bag_ += f.error_full.on_changed ([
this](
const std::optional<::aria::Error>&) {
199 using ValueT = std::remove_reference_t<
decltype(f.value.get())>;
200 bag_ += f.value.on_changed([
this](
const ValueT&) { recompute_(); });
201 if constexpr (
requires { f.validator.state(); }) {
202 bag_ += f.validator.state().on_changed([
this](
const ValidationState&) { recompute_(); });
211 template<std::predicate Pred>
212 void rule(Pred predicate, std::string message,
213 std::string rule_id_value = {}) {
214 if (rule_id_value.empty()) {
215 rule_id_value =
"form_rule_" + std::to_string(rules_.size());
217 rules_.push_back(Rule{
218 std::function<bool()>(std::move(predicate)),
220 std::move(rule_id_value),
242 std::function<bool()> valid;
243 std::function<bool()> dirty;
244 std::function<bool()> pending;
245 std::function<std::optional<::aria::Error>()> error;
248 std::function<bool()> predicate;
254 const auto revision = revision_;
255 const auto rules = rules_;
256 bool all_valid =
true;
257 bool any_dirty =
false;
258 bool any_pending =
false;
259 std::optional<::aria::Error> headline;
261 for (
const auto& r : rules) {
262 const bool passed = r.predicate();
263 if (revision != revision_)
return;
268 ValidationKey{std::string{}, r.rule_id},
270 e.
source =
"FormValidator";
271 headline = std::move(e);
275 for (
auto& f : fields_) {
276 const bool v = f.valid();
277 const bool d = f.dirty();
278 const bool p = f.pending();
279 all_valid = all_valid && v;
280 any_dirty = any_dirty || d;
281 any_pending = any_pending || p;
282 if (!headline && !v) {
283 headline = f.error();
292 first_error = headline ? headline->message : std::string{};
296 std::vector<FieldHooks> fields_;
297 std::vector<Rule> rules_;
298 SubscriptionBag bag_;
299 std::size_t revision_ = 0;
Definition validator.hpp:135
std::function< std::optional< std::string >(const T &)> Rule
User-supplied rule body: returns a message when the value fails, std::nullopt when it passes.
Definition validator.hpp:142
const std::string & field_path() const noexcept
Definition validator.hpp:167
Definition property.hpp:103
::aria::Subscription on_changed(std::function< void(const T &)> fn)
Run fn(new_value) every time the value changes.
Definition property.hpp:200
Definition binding_engine.hpp:25
auto batch(Fn &&fn) -> decltype(fn())
Sugar: batch([&]{ firstName = "..."; lastName = "..."; }).
Definition graph.hpp:369
validation_dsl::RulePart rule_id(std::string id) noexcept
Definition validation_key.hpp:96
Definition validation_key.hpp:110
static Error validation(ValidationKey k, std::string msg)
Hard validation error.
Definition error.hpp:170
std::string source
Free-form locator: which subsystem produced this.
Definition error.hpp:136
Definition validator.hpp:34
std::vector< Error > errors
Definition validator.hpp:36
bool valid
Definition validator.hpp:35
Definition validator.hpp:61