What This Demonstrates
The standard handle-change handler works for
inputs that produce a single value: text fields, checkboxes, single
selects. But a multi-select <select multiple>
produces a collection of selected values. For these cases, use
set-handle-change to programmatically set
the value to whatever shape you need.
The Code
The initial value is an empty vector. On each change event, the handler extracts all selected options from the DOM and sets the value as a sequence:
(ns multiple-dropdown
(:require
[fork.reagent :as fork]))
(defn view []
[fork/form {:initial-values {"status" []}}
(fn [{:keys [set-handle-change handle-blur values]}]
[:form
[:select
{:multiple true
:name "status"
:value (values "status")
:on-change
#(set-handle-change
{:value
(let [opts (array-seq
(-> % .-target .-options))]
(keep (fn [x]
(when (.-selected x)
(.-value x)))
opts))
:path ["status"]})
:on-blur handle-blur}
[:option {:value "married"} "Married"]
[:option {:value "single"} "Single"]
[:option {:value "pns"} "Prefer Not To Say"]]])])How It Works
set-handle-change accepts a map with two keys:
-
:value— the new value to set. Can be any type (string, number, vector, map). Can also be a function that receives the current value and returns the new one. -
:path— the path in the values map where the value should be written. A vector, e.g.["status"].
This is the escape hatch for any input that doesn't fit the standard
handle-change pattern (which reads the name
and value from the DOM event). Use it for multi-selects, custom
components, drag-and-drop uploads, or any case where you need to
compute the value yourself.