Skip to content

Instantly share code, notes, and snippets.

@spencerldixon
Created June 8, 2023 16:47
Show Gist options
  • Save spencerldixon/ad088cef80f2a99bb8c7b8e758b1a881 to your computer and use it in GitHub Desktop.
Save spencerldixon/ad088cef80f2a99bb8c7b8e758b1a881 to your computer and use it in GitHub Desktop.
Parent / Child slim-select async Stimulus controllers
import { Controller } from "@hotwired/stimulus";
import SlimSelect from 'slim-select';
// A generic base controller for doing async API searching via slim select with baked in rate limiting
// You'll can extend this controller and define two methods, query(searchTerm) for your GraphQL query,
// and formatData(data) to format your data for presentation
export default class extends Controller {
static targets = ["selector"]
static values = {
placeholder: { type: String, default: "Click here to search" }
}
connect() {
let _this = this
this.slimSelectInstance = new SlimSelect({
select: this.selectorTarget,
settings: {
placeholderText: this.placeholderValue,
},
events: {
search: (search, currentData) => {
return new Promise((resolve, reject) => {
if (search.length < 3) {
return reject("Search must be at least 2 characters")
}
_this.rateLimitedSearch(search, resolve)
})
}
}
})
}
clear() {
this.slimSelectInstance.setData([])
}
rateLimitedSearch(searchTerm, callback, timeout=200) {
clearTimeout(this.timeout)
this.timeout = setTimeout(() => {
this.search(searchTerm, callback);
}, timeout)
}
search(searchTerm, callback) {
let _this = this
fetch('/graphql', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query: _this.query(searchTerm)
})
}).then(function (response) {
return response.json()
}).then(function (json) {
// Upon successful fetch send data to callback function.
// Be sure to send data back in the proper format.
// Refer to the method setData for examples of proper format.
callback(_this.formatData(json.data))
}).catch(function(error) {
// If any errors happened send false back through the callback
callback(false)
})
}
query(searchTerm) {
return `query {}`
}
formatData(data) {
return data
}
}
import SelectAsyncBaseController from "./select_async_base_controller.js"
import SlimSelect from 'slim-select';
// Extends select async base controller to search areas
// Define your own query(searchTerm) and formatData(data) methods
export default class extends SelectAsyncBaseController {
static targets = ["selector"]
static values = {
placeholder: { type: String, default: "Click here to search" }
}
query(searchTerm) {
return `
query {
focusAreas(search: "${searchTerm}") {
id
name
}
}
`
}
formatData(data) {
const formattedData = data.focusAreas.map(function(item) {
return {
text: item.name,
value: item.id
}
})
return formattedData
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment