Last active
November 27, 2020 17:58
-
-
Save geraldodev/a7815550642e6056cdb849e1e0522c0c to your computer and use it in GitHub Desktop.
Thin layer over mui autocomplete.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns app.helix_autocomplete | |
(:require | |
["@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) | |
label-field) | |
value-field (if (keyword? value-field) | |
(name value-field) | |
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) | |
empty-obj | |
v)] | |
; (prn "change to " v) | |
(reset! value-ref v) | |
(on-change e (not-empty (gobj/get v value-field value-field)) reason))) | |
:value | |
(let [v | |
(if (nil? value) | |
empty-obj | |
(let [cached-field (gobj/get @value-ref value-field)] | |
(if (= cached-field value) | |
@value-ref | |
(let [new-cached-value | |
(if (or (nil? value) (empty? js-options)) | |
empty-obj | |
(loop [idx 0] | |
(let [record (gobj/get js-options idx)] | |
(if (= (gobj/get record value-field) value) | |
record | |
(if (< (inc idx) (.-length js-options)) | |
(recur (inc idx)) | |
empty-obj)))))] | |
; (prn "new-cached " new-cached-value) | |
(reset! value-ref new-cached-value) | |
@value-ref))))] | |
; (js/console.log "Value abaixo") | |
; (js/console.log v) | |
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))))}))) |
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
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.