untangled

NEW CHANNEL: #fulcro
cjmurphy 2017-06-25T04:10:05.261401Z

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.

tony.kay 2017-06-25T05:17:20.400371Z

@cjmurphy I don’t think, at the moment, it generates events. The form support is young. There is the on-form-change support.

tony.kay 2017-06-25T05:17:47.401206Z

You could easily augment the ::dropdown form-field rendering and add support for a callback

tony.kay 2017-06-25T05:18:21.402129Z

around line 890 of forms.cljc

tony.kay 2017-06-25T05:18:36.402544Z

in params

cjmurphy 2017-06-25T05:18:50.402954Z

was thinking might have to do something like that but looked a bit tricky so thought I'd ask first.

tony.kay 2017-06-25T05:19:35.404397Z

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.

cjmurphy 2017-06-25T05:19:40.404520Z

So i'll actually have to make a change to the library, or it should be able to handle it?

tony.kay 2017-06-25T05:19:49.404766Z

improve the library

tony.kay 2017-06-25T05:20:06.405440Z

I think that is a valid use-case: wanting to add you own additional event handling to change events

cjmurphy 2017-06-25T05:20:19.405936Z

Ideally would events be in the forms-spec?

tony.kay 2017-06-25T05:20:26.406211Z

no

tony.kay 2017-06-25T05:20:33.406463Z

forms-spec is data

tony.kay 2017-06-25T05:20:36.406583Z

goes in app state

tony.kay 2017-06-25T05:20:42.406745Z

functions cannot go in there.

cjmurphy 2017-06-25T05:20:53.407088Z

okay

tony.kay 2017-06-25T05:20:55.407130Z

Technically, you could add a transaction’s content

tony.kay 2017-06-25T05:20:59.407253Z

to form-spec

tony.kay 2017-06-25T05:21:06.407458Z

but then you’d have to deal with parameters somehow

tony.kay 2017-06-25T05:22:23.409872Z

‘[(do-thing {:value ???})]` is valid data, and we could technically invent a placeholder for the current value

tony.kay 2017-06-25T05:22:34.410166Z

heck, ??? is a legal sym

tony.kay 2017-06-25T05:22:35.410194Z

😉

tony.kay 2017-06-25T05:23:20.411436Z

but I think it makes more sense as a parameter to the field rendering itself.

cjmurphy 2017-06-25T05:23:25.411641Z

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"

tony.kay 2017-06-25T05:23:51.412391Z

yes

tony.kay 2017-06-25T05:23:56.412564Z

is there a question there?

cjmurphy 2017-06-25T05:24:13.413080Z

So the custom one. mine, can just come after?

tony.kay 2017-06-25T05:24:42.414058Z

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))))

tony.kay 2017-06-25T05:24:53.414375Z

you can see the transact there 2/3rds down

cjmurphy 2017-06-25T05:25:00.414628Z

I really want a 'post change' event on the field.

tony.kay 2017-06-25T05:25:47.415987Z

right…so now you’re saying (form-field this form :dropdown), right?

cjmurphy 2017-06-25T05:25:56.416209Z

Yes

tony.kay 2017-06-25T05:26:07.416584Z

The form-field multimethod supports params

tony.kay 2017-06-25T05:26:13.416730Z

but dropdown ignores them

cjmurphy 2017-06-25T05:26:32.417292Z

get-custom-on-form-change-mutation

tony.kay 2017-06-25T05:26:34.417364Z

so you could say (form-field this form :dropdown :onChange (fn [new-val] ...))

tony.kay 2017-06-25T05:26:51.417867Z

and add that to the implementation of dropdown’s render in the lib

tony.kay 2017-06-25T05:27:09.418486Z

OR copy the dropdown rendering code, and add it to your own type of field…but that would be kinda silly

cjmurphy 2017-06-25T05:27:24.418937Z

New code would be picking up the onChange.

tony.kay 2017-06-25T05:27:29.419098Z

yep

tony.kay 2017-06-25T05:27:35.419300Z

and just running it in the onChange of the input

tony.kay 2017-06-25T05:27:41.419561Z

along with the built-in form stuff

tony.kay 2017-06-25T05:27:48.419698Z

it is a trivial change/improvement

tony.kay 2017-06-25T05:27:59.420016Z

most of the form fields should have it

tony.kay 2017-06-25T05:28:03.420109Z

but they don’t

cjmurphy 2017-06-25T05:28:18.420624Z

okay - if its trivial I'll be able to do it 😉

tony.kay 2017-06-25T05:28:23.420723Z

😄

tony.kay 2017-06-25T05:28:34.421021Z

the code I just posted is the current impl

tony.kay 2017-06-25T05:28:53.421597Z

you can see params already there. Change it to {:keys [onChange]} and then run the onChange in the input

tony.kay 2017-06-25T05:29:01.421806Z

with the new value

tony.kay 2017-06-25T05:29:17.422255Z

I think the new value…does that seem right? Or should it be the event?

tony.kay 2017-06-25T05:29:35.422858Z

could also be both, for convenience, but that is kinda heavy handed

tony.kay 2017-06-25T05:31:08.426587Z

actually, I think you need to pass the value (optionally the event), because form fields support transform functions

tony.kay 2017-06-25T05:31:13.426721Z

forgot about that

cjmurphy 2017-06-25T05:31:17.426855Z

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...

tony.kay 2017-06-25T05:31:50.427947Z

yeah, the forms stuff is young, but it already shows the huge promise

tony.kay 2017-06-25T05:31:55.428186Z

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.

tony.kay 2017-06-25T13:36:26.509658Z

@cjmurphy Merged and released to clojars 1.0.0-SNAPSHOT

tony.kay 2017-06-25T13:55:24.564307Z

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.

tony.kay 2017-06-25T13:56:29.567334Z

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.

cjmurphy 2017-06-25T15:26:58.853412Z

Setting the :input/default-value on my dropdowns got rid of their "nothing" (`:untangled.ui.forms/none`) options perfectly :simple_smile: