Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Thin layer over mui autocomplete.
(ns app.helix_autocomplete
["@material-ui/lab/Autocomplete" :default Autocomplete]
["@material-ui/core/TextField" :default TextField]
["react" :as r]
[goog.object :as gobj]
(defnc AutocompleteHelix
[{:keys [id js-options label label-field value-field value on-change style]}]
(let [label-field (if (keyword? label-field)
(name label-field)
value-field (if (keyword? value-field)
(name value-field)
get-option-label-fn #(gobj/get % label-field "")
get-option-selected-fn #(gobj/get % value-field "")
empty-obj (clj->js {label-field ""
value-field ""})
empty-obj? (fn [obj]
(= empty-obj obj))
value-ref (hooks/use-ref empty-obj)
($ ^:native Autocomplete
{:id id
:default-value empty-obj
:options (or js-options #js [])
:get-option-label get-option-label-fn
:get-option-selected get-option-selected-fn
:on-change (fn [e v reason]
; (js/console.log (str "change " reason))
; (js/console.log v)
(let [v (if (nil? v)
; (prn "change to " v)
(reset! value-ref v)
(on-change e (not-empty (gobj/get v value-field value-field)) reason)))
(let [v
(if (nil? value)
(let [cached-field (gobj/get @value-ref value-field)]
(if (= cached-field value)
(let [new-cached-value
(if (or (nil? value) (empty? js-options))
(loop [idx 0]
(let [record (gobj/get js-options idx)]
(if (= (gobj/get record value-field) value)
(if (< (inc idx) (.-length js-options))
(recur (inc idx))
; (prn "new-cached " new-cached-value)
(reset! value-ref new-cached-value)
; (js/console.log "Value abaixo")
; (js/console.log v)
:style style
:render-input (fn [params]
(.createElement r TextField
(doto (js/Object.assign #js {} params)
(gobj/set "label" label)
(gobj/set "InputLabelProps" #js {:shrink true} )
(gobj/set "fullWidth" true))))})))
Copy link

It's suposed to be used controlled, by supplying value and on-change. js-options is Autocomplete's options. I've changed the name to make clear that is a javascript vector of objects. label-field is the name of the field on the js object that is correspondent to the label that is going to be presented to the user. value-field is the name of the field on the js object that is going to be updated on your database (the id field). Mui Autocomplete expectas an js object as a value parameter. This layer computes that value (clj->js {label-field "john" value-field 1}) for you, so you can pass 1 to value. It caches the last computed object so it does not recompute the object on every render if the value-field is the same. Not so polished code, but you get the idea.

Copy link

geraldodev commented Nov 26, 2020

It can be used like

($ AutocompleteHelix {:id "mylookup" :js-options #js [{:name "john" :id "1"}] :label "Client" :label-field :name :value-field :id :value simple-cljs-variable-that-has-the-id-of-the-client :on-change (fn [e value reason] (setter-from-helix-use-state-hook assoc :client-id value)) :style {:width "200px"})
Only js here is the table that is going to be displayed by the control. I'm fetching as js from the server, and keeping it on a hook up the three and receiving it as a parameter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment