esc

Type to search...

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:

multiple_dropdown.cljs
(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.