I've been working on a linked text-box and list-component, similar to a combobox or typeahead component. I want to be able type free text into the text-box, unless an item from the list is clicked, in which case overwrite the text-box with the selected item's text.
These two components are contained in a single, parent div, which owns the ratom that maintains the selection state. The ratom is initally nil, but is updated when a list-item is selected. I'd like the text-box's value to be updated only when the ratom's contents are not nil, and premit free entry when the ratom's value is nil.
Unfortunately, this works only for the second distinct click of the list-component, and thereafter. The text-box does not update on the first click, even though console inspection shows that it's value attribute is updated. So, it looks like a question of triggering rendering.
Here's the code (uses dommy)...
(defn text-box [selection]
[:input.jdropbtn
(into
{:type :text
:placeholder "Dropdown"
:on-change #(.log js/console
(let [v (-> % .-target .-value)
opts (-> % .-target .-nextSibling dom/children array-seq)]
;(doseq [t opts] (dom/toggle! t (clojure.string/includes? (dom/text t) v)))
))}
(when @selection
{:value (:value @selection)} ) ; This fails on first selection!
; {:value (:value @selection)} ; This prevents free typing!
)
]
)
(defn list-component [selection data-key items]
[:div.jdropdown-content
(for [i items]
(let [{:keys [id value] :as item} i]
^{:key id} [:a {data-key id :on-click #(reset! selection {:id id :value value}) } value])
)
]
)
;;;;;;;;;;;;;; parent
(defn my-droplist [data-key items]
(let [selection (r/atom nil) ]
(fn []
[:div.jdropdown {:id "jack"}
[text-box selection]
[list-component selection data-key items]
])
))
; invoked as:
[my-droplist :data-appid
[{:id 11 :value "Hey there!"}
{:id 22 :value "Hi there!"}
{:id 33 :value "Ho there!"}]]
Styling is essentially the same as the dropdown menu css example from w3schools (http://www.w3schools.com/css/css_dropdowns.asp).
TIA.