Skip to content

Commit

Permalink
Wait until end of options stream to commit an async filter (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
josefarias authored Feb 29, 2024
1 parent 5fae4b0 commit 7ed731f
Show file tree
Hide file tree
Showing 9 changed files with 38 additions and 38 deletions.
12 changes: 9 additions & 3 deletions app/assets/javascripts/controllers/hw_combobox_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ export default class HwComboboxController extends Concerns(...concerns) {
"dialogCombobox",
"dialogFocusTrap",
"dialogListbox",
"endOfOptionsStream",
"handle",
"hiddenField",
"listbox",
"paginationFrame"
"listbox"
]

static values = {
Expand Down Expand Up @@ -70,7 +70,13 @@ export default class HwComboboxController extends Concerns(...concerns) {
}
}

paginationFrameTargetConnected() {
endOfOptionsStreamTargetConnected(element) {
const inputType = element.dataset.inputType

this._preselectOption()

if (inputType) {
this._commitFilter({ inputType })
}
}
}
4 changes: 0 additions & 4 deletions app/assets/javascripts/hw_combobox/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,6 @@ export function startsWith(string, substring) {
return string.toLowerCase().startsWith(substring.toLowerCase())
}

export function nextFrame() {
return new Promise(requestAnimationFrame)
}

export function debounce(fn, delay = 150) {
let timeoutId = null

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ Combobox.Autocomplete = Base => class extends Base {
}
}

_maybeAutocompleteWith(option, { force }) {
_autocompleteWith(option, { force }) {
if (!this._autocompletesInline && !force) return

const typedValue = this._actingCombobox.value
const typedValue = this._query
const autocompletedValue = option.getAttribute(this.autocompletableAttributeValue)

if (force) {
this._actingCombobox.value = autocompletedValue
this._query = autocompletedValue
this._actingCombobox.setSelectionRange(autocompletedValue.length, autocompletedValue.length)
} else if (startsWith(autocompletedValue, typedValue)) {
this._actingCombobox.value = autocompletedValue
this._query = autocompletedValue
this._actingCombobox.setSelectionRange(typedValue.length, autocompletedValue.length)
}
}
Expand All @@ -30,14 +30,14 @@ Combobox.Autocomplete = Base => class extends Base {
}

get _isExactAutocompleteMatch() {
return this._immediatelyAutocompletableValue === this._actingCombobox.value
return this._immediatelyAutocompletableValue === this._query
}

// All `_isExactAutocompleteMatch` matches are `_isPartialAutocompleteMatch` matches
// but not all `_isPartialAutocompleteMatch` matches are `_isExactAutocompleteMatch` matches.
get _isPartialAutocompleteMatch() {
return !!this._immediatelyAutocompletableValue &&
startsWith(this._immediatelyAutocompletableValue, this._actingCombobox.value)
startsWith(this._immediatelyAutocompletableValue, this._query)
}

get _autocompletesList() {
Expand Down
4 changes: 2 additions & 2 deletions app/assets/javascripts/hw_combobox/models/combobox/dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Combobox.Dialog = Base => class extends Base {
}

_moveArtifactsToDialog() {
this.dialogComboboxTarget.value = this._actingCombobox.value
this.dialogComboboxTarget.value = this._query

this._actingCombobox = this.dialogComboboxTarget
this._actingListbox = this.dialogListboxTarget
Expand All @@ -23,7 +23,7 @@ Combobox.Dialog = Base => class extends Base {
}

_moveArtifactsInline() {
this.comboboxTarget.value = this._actingCombobox.value
this.comboboxTarget.value = this._query

this._actingCombobox = this.comboboxTarget
this._actingListbox = this.listboxTarget
Expand Down
30 changes: 14 additions & 16 deletions app/assets/javascripts/hw_combobox/models/combobox/filtering.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

import Combobox from "hw_combobox/models/combobox/base"
import { applyFilter, nextFrame, debounce, isDeleteEvent } from "hw_combobox/helpers"
import { applyFilter, debounce, isDeleteEvent } from "hw_combobox/helpers"
import { get } from "hw_combobox/vendor/requestjs"

Combobox.Filtering = Base => class extends Base {
Expand All @@ -21,20 +21,13 @@ Combobox.Filtering = Base => class extends Base {
}

async _filterAsync(event) {
const q = this._actingCombobox.value.trim()

await get(this.asyncSrcValue, { responseKind: "turbo-stream", query: { q } })

this._afterTurboStreamRender(() => this._commitFilter(event))
const query = { q: this._query, input_type: event.inputType }
await get(this.asyncSrcValue, { responseKind: "turbo-stream", query })
}

_filterSync(event) {
const query = this._actingCombobox.value.trim()

this.open()

this._allOptionElements.forEach(applyFilter(query, { matching: this.filterableAttributeValue }))

this._allOptionElements.forEach(applyFilter(this._query, { matching: this.filterableAttributeValue }))
this._commitFilter(event)
}

Expand All @@ -48,12 +41,17 @@ Combobox.Filtering = Base => class extends Base {
}
}

async _afterTurboStreamRender(callback) {
await nextFrame()
callback()
get _isQueried() {
return this._query.length > 0
}

get _isQueried() {
return this._actingCombobox.value.length > 0
// Consider +_query+ will contain the full autocompleted value
// after a certain point in the call chain.
get _query() {
return this._actingCombobox.value.trim()
}

set _query(value) {
this._actingCombobox.value = value
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Combobox.Selection = Base => class extends Base {

_connectSelection() {
if (this.hasPrefilledDisplayValue) {
this._actingCombobox.value = this.prefilledDisplayValue
this._query = this.prefilledDisplayValue
}
}

Expand All @@ -19,7 +19,7 @@ Combobox.Selection = Base => class extends Base {

if (option) {
this._markValid()
this._maybeAutocompleteWith(option, { force })
this._autocompleteWith(option, { force })
this._commitSelection(option, { selected: true })
} else {
this._markInvalid()
Expand Down Expand Up @@ -52,7 +52,7 @@ Combobox.Selection = Base => class extends Base {

_selectNew() {
this._resetOptions()
this.hiddenFieldTarget.value = this._actingCombobox.value
this.hiddenFieldTarget.value = this._query
this.hiddenFieldTarget.name = this.nameWhenNewValue
}

Expand Down
2 changes: 1 addition & 1 deletion app/views/hotwire_combobox/_pagination.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%# locals: (for_id:, src:) -%>

<%= turbo_frame_tag hw_pagination_frame_id(for_id), src: src, loading: :lazy,
data: { hw_combobox_target: "paginationFrame" } %>
data: { hw_combobox_target: "endOfOptionsStream", input_type: params[:input_type] } %>
4 changes: 2 additions & 2 deletions test/fixtures/movies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
"A Few Good Men",
"A Nightmare on Elm Street",
"A Quiet Place",
"A Star is Born (2018)",
"A Star is Born",
"A Streetcar Named Desire",
"Aladdin (1992)",
"Aladdin",
"Alien",
"Aliens",
"Amadeus",
Expand Down
2 changes: 1 addition & 1 deletion test/system/hotwire_combobox_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,6 @@ def click_away
end

def click_on_top_left_corner
page.execute_script("document.elementFromPoint(0, 0).click()")
page.execute_script "document.elementFromPoint(0, 0).click()"
end
end

0 comments on commit 7ed731f

Please sign in to comment.