Typeahead field in re-frame

clojurescript

#1

Any suggestions on how to implement a lookahead field in re-frame? I see that the reagent-forms library has one, but support for re-frame is new and I am having trouble following the existing documentation. For some reason I can’t get the field to render, and since there is so much going on with reagent-forms I’m unsure where my problem lies.

Is there a more straightforward means of implementing this that others have used?
Thanks…


#2

To be honest, I just implement one when I need it in a project. You can do it without re-frame, which I like to do for something this simple:

  • Two components, one for the input control, one as a wrapper
  • Local state atom for the input control, with the usual on-change swap for value
  • Local state atom for the typeahead, storing loading status, data and flags for what’s visible
  • Typeahead passes a debounced on-change for the input, which the input wraps to facilitate the direct render from its local state. The debounced on-change is created via goog.functions/debounce and triggers the fetch logic for the typeahead
  • Result rendering is done in the typeahead, optionally in a third component

You can also pass in fetch configuration and/or render functions to the typeahead, just pass them as props. Makes for a nice re-usable component.

If you’re bent on using re-frame for this, I’d still recommend using an atom for the input control, and some sort of ID for each typeahead instance to track its state via re-frame. I like to use a globally defined goog.ui.IdGenerator and a helper function to get one (think it’s cheaper than (random-uuid) or sth):

(ns myapp.ui
  (:require [goog.ui :as ui]))

(defonce id-gen 
  (ui/IdGenerator.))

(defn next-id []
  (.getNextUniqueId id-gen))

When a typahead is created, it creates an ID for itself and “scopes” respective re-frame events by it. You can use this to keep results for each instance apart, and/or pass in a fixed ID via props to sync/share/persist the typeahead state.

Don’t know if it’ll help much, but this is sort what I’m talking about (although I wrote it in one go and didn’t run anything from it :sweat_smile:): https://gist.github.com/madbonkey/baf1417be520b27cf94a1fb14637ecbe


#3

I’d go with react-select or some other React component.


#4

+1 It’s a well tested library. We are using it with Rum as a base select component and building more sophisticated ones on top of it.


#5