I have a form with a form-spec
that includes a f/dropdown-input
. I'm looking for the event that 'the user has selected a different value' - I need to transact!
a mutation when this happens. It is not clear to me how to go about hooking into the event.
@cjmurphy I don’t think, at the moment, it generates events. The form support is young. There is the on-form-change support.
You could easily augment the ::dropdown form-field rendering and add support for a callback
around line 890 of forms.cljc
in params
was thinking might have to do something like that but looked a bit tricky so thought I'd ask first.
not that tricky…there isn’t much to the forms support internally. It just makes a copy of the original field values. The field rendering just hooks up the change events.
So i'll actually have to make a change to the library, or it should be able to handle it?
improve the library
I think that is a valid use-case: wanting to add you own additional event handling to change events
Ideally would events be in the forms-spec?
no
forms-spec is data
goes in app state
functions cannot go in there.
okay
Technically, you could add a transaction’s content
to form-spec
but then you’d have to deal with parameters somehow
‘[(do-thing {:value ???})]` is valid data, and we could technically invent a placeholder for the current value
heck, ???
is a legal sym
😉
but I think it makes more sense as a parameter to the field rendering itself.
I can see in the transaction log: [:user-request/by-id USER-REQUEST-FORM] transacted '[(untangled.ui.forms/select-option {:form-id [:user-request/by-id USER-REQUEST-FORM], :field :request/period, :value ":q2"}) {:root/user-request [:untangled.ui.forms/form-root]}], #uuid "95d35c63-658f-4c24-a9bc-6452dfeda882"
yes
is there a question there?
So the custom one. mine, can just come after?
Ah, so if you were going to improve the lib, the current imple of rendering of that looks:
(defmethod form-field* ::dropdown [component form field-name & params]
(let [id (form-ident form)
selection (current-value form field-name)
cls (or (css-class form field-name) "form-control")
field (field-config form field-name)
optional? (= ::none (:input/default-value field))
options (:input/options field)]
(dom/select #js
{:name field-name
:className cls
:value selection
:onChange (fn [event]
(let [value (.. event -target -value)
field-info {:form-id id
:field field-name
:value value}]
(om/transact! component
`[(select-option ~field-info)
~@(get-on-form-change-mutation form field-name :edit)
~form-root-key])))}
(when optional?
(dom/option #js {:value ::none} ""))
(map (fn [{:keys [option/key option/label]}]
(dom/option #js {:key key :value key} label))
options))))
you can see the transact there 2/3rds down
I really want a 'post change' event on the field.
right…so now you’re saying (form-field this form :dropdown)
, right?
Yes
The form-field multimethod supports params
but dropdown ignores them
get-custom-on-form-change-mutation
so you could say (form-field this form :dropdown :onChange (fn [new-val] ...))
and add that to the implementation of dropdown’s render in the lib
OR copy the dropdown rendering code, and add it to your own type of field…but that would be kinda silly
New code would be picking up the onChange.
yep
and just running it in the onChange of the input
along with the built-in form stuff
it is a trivial change/improvement
most of the form fields should have it
but they don’t
okay - if its trivial I'll be able to do it 😉
😄
the code I just posted is the current impl
you can see params already there. Change it to {:keys [onChange]}
and then run the onChange
in the input
with the new value
I think the new value…does that seem right? Or should it be the event?
could also be both, for convenience, but that is kinda heavy handed
actually, I think you need to pass the value (optionally the event), because form fields support transform functions
forgot about that
Not sure, I'll get to this later today. Thanks - this forms stuff will become very good very soon. I'm forgetting CSS for the moment, next week...
yeah, the forms stuff is young, but it already shows the huge promise
just needs these little details, which are better written as we hit some use cases. I have not had the chance to use it much yet.
@cjmurphy Merged and released to clojars 1.0.0-SNAPSHOT
on dropdowns: If you set a default then it won’t show a “nothing” option. If you want it to show something like required, then just add an entry for “required” that your form validation won’t accept as a value.
You have to use form, not field, validation for that (since dropdowns are technically always valid because they are pegged to values you’ve provided)…so either write something on your submit that prevents commit, or use the on-form-change support.
Setting the :input/default-value
on my dropdowns got rid of their "nothing" (`:untangled.ui.forms/none`) options perfectly :simple_smile: