Closed dpetranek closed 3 years ago
You're right, guards are pure functions which could not update the context.
For now you can add a "validating" state, which has an entry
action that does the validation and stores the error (if any) in the context, and use an eventless transition (:always
) that do the transition based on the error.
I think this could be a common requirement, would think about if there is any better way to support such use cases.
You know, I tried it out today and I think I like having validation be its own state. Thanks for the guidance, here's what I came up with:
(def simple-sign-in
(fsm/machine
{:id :simple-sign-in
:initial :ready
:states
{:ready {:on {:submit :validate}
:states {:error {:exit (fsm/assign (fn [state _] (assoc state :errors nil)))}}}
:validate {:entry (fsm/assign (fn [state event] (assoc state :errors (validate event))))
:always [{:target [:> :ready :error]
:guard (fn [state _] (:errors state))}
{:target :submitting}]}
:submitting {:on {:submit-success {:target :ready
:actions (fn [_ _] (println "dispatching submit success"))}
:submit-failure {:target [:> :ready :error]
:actions (fn [_ event] (println "dispatching submit fail" '))}}}}}))
I do think it would be helpful to discuss some "best practices" in the docs, though. Thanks again, I think this library is brilliant!
I'm finding this library very useful, but I'm struggling with the best way to handle validation, as for a re-frame form.
Here's my setup:
In transitioning from
:ready
(or[:> :ready :error]
), I'm guarding the transition to the:error
state by running the validation function. Unfortunately, the:guard
throws away its return value, so I have to run it again in the:actions
step.Is there a way to pass the return value of the guard into the machine context? I tried messing about with
assign
, but doesn't really work because I think you need to return the machine state, which would mean the:guard
always passes. Or maybe I'm just barking up the wrong tree, but I can't figure out how to do validation without validating twice.