Skip to content

Instantly share code, notes, and snippets.

@vlaaad
Created January 3, 2019 18:13
Show Gist options
  • Select an option

  • Save vlaaad/c215c2cce52b96b98deee29a35bcc57c to your computer and use it in GitHub Desktop.

Select an option

Save vlaaad/c215c2cce52b96b98deee29a35bcc57c to your computer and use it in GitHub Desktop.

Map events

Consider this example:

(defn todo-view [{:keys [text id done]}]
  {:fx/type :h-box
   :children [{:fx/type :check-box
               :selected done
               :on-selected-changed #(swap! *state assoc-in [:by-id id :done] %)
              {:fx/type :label
               :style {:-fx-text-fill (if done :grey :black)}
               :text text}]})

There are problems with using functions as event handlers:

  1. Performing mutation from these handlers requires coupling with that state, thus making todo-view dependent on mutable *state
  2. Updating state from listeners complects logic with view, making application messier over time
  3. There are unnecessary reassignments to on-selected-changed: functions have no equality semantics other than their identity, so on every change to this view (for example, when changing it's text), on-selected-changed will be replaced with another function with same behavior.

To mitigate these problems, cljfx allows to define event handlers as arbitrary maps, and provide a function to an app that performs actual handling of these map-events (with additional :fx/event key containing dispatched event):

;; Define view as just data

(defn todo-view [{:keys [text id done]}]
  {:fx/type :h-box
   :spacing 5
   :padding 5
   :children [{:fx/type :check-box
               :selected done
               :on-selected-changed {:event/type ::set-done :id id}}
              {:fx/type :label
               :style {:-fx-text-fill (if done :grey :black)}
               :text text}]})

;; Define single map-event-handler that does mutation

(defn map-event-handler [event]
  (case (:event/type event)
    ::set-done (swap! *state assoc-in [:by-id (:id event) :done] (:fx/event event))))

;; Provide map-event-handler to app as an option

(cljfx/mount-app
  *state
  (cljfx/create-app
    :middleware (cljfx/wrap-map-desc assoc :fx/type root)
    :opts {:fx.opt/map-event-handler map-event-handler}))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment