Class: AutocompleteComponent
- Inherits:
-
Funicular::Component
- Object
- Funicular::Component
- AutocompleteComponent
- Defined in:
- lib/components/autocomplete_component.rb
Overview
Incremental-search combobox over a fixed option list.
component Funicular::Plugins::Autocomplete::Component,
key: "brewery-#{record_id}", # remount to re-read value:
options: [{ "id" => 1, "label" => "Masuizumi" }, ...],
value: selected_id, # optional preselection
input_id: "brewery-search",
input_class: "...",
placeholder: "Search...",
empty_label: "No matches",
limit: 20,
on_select: ->(option) { ... } # receives the chosen Hash
The parent owns the option list; filtering is a client-side
case-insensitive substring match on "label". The value prop is read
once at mount to prefill the input, so give the component a key that
changes when the selection context changes.
Instance Method Summary collapse
- #component_mounted ⇒ Object
- #handle_blur(_event) ⇒ Object
- #handle_focus(_event) ⇒ Object
- #handle_input(_event) ⇒ Object
- #handle_key(event) ⇒ Object
- #initialize_state ⇒ Object
- #render ⇒ Object
- #select_option(option) ⇒ Object
Instance Method Details
#component_mounted ⇒ Object
23 24 25 26 |
# File 'lib/components/autocomplete_component.rb', line 23 def component_mounted prefill = selected_label set_input(prefill) if prefill end |
#handle_blur(_event) ⇒ Object
37 38 39 40 |
# File 'lib/components/autocomplete_component.rb', line 37 def handle_blur(_event) # Option mousedown fires before blur, so selection still wins. patch(open: false) end |
#handle_focus(_event) ⇒ Object
33 34 35 |
# File 'lib/components/autocomplete_component.rb', line 33 def handle_focus(_event) patch(open: true) end |
#handle_input(_event) ⇒ Object
28 29 30 31 |
# File 'lib/components/autocomplete_component.rb', line 28 def handle_input(_event) node = @refs[:query_input] patch(query: node ? node[:value].to_s : "", open: true, highlight: 0) end |
#handle_key(event) ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/components/autocomplete_component.rb', line 42 def handle_key(event) key = event[:key].to_s if key == "Escape" patch(open: false) elsif key == "ArrowDown" move_highlight(1) elsif key == "ArrowUp" move_highlight(-1) elsif key == "Enter" && state[:open] shown = option = shown[state[:highlight]] || shown[0] select_option(option) if option end end |
#initialize_state ⇒ Object
19 20 21 |
# File 'lib/components/autocomplete_component.rb', line 19 def initialize_state { query: nil, open: false, highlight: 0 } end |
#render ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/components/autocomplete_component.rb', line 64 def render div(class: "funicular-autocomplete") do input( type: "text", ref: :query_input, id: props[:input_id], class: "funicular-autocomplete__input #{props[:input_class]}", placeholder: props[:placeholder].to_s, autocomplete: "off", oninput: :handle_input, onfocus: :handle_focus, onblur: :handle_blur, onkeydown: :handle_key ) if state[:open] render_panel end end end |
#select_option(option) ⇒ Object
57 58 59 60 61 62 |
# File 'lib/components/autocomplete_component.rb', line 57 def select_option(option) patch(query: nil, open: false, highlight: 0) set_input(option["label"].to_s) callback = props[:on_select] callback.call(option) if callback end |