Created
June 8, 2023 16:47
-
-
Save spencerldixon/ad088cef80f2a99bb8c7b8e758b1a881 to your computer and use it in GitHub Desktop.
Parent / Child slim-select async Stimulus controllers
This file contains 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
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 | |
} | |
} |
This file contains 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
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