Async Select Widget for NetlifyCMS
A select widget for NetlifyCMS widget that allows you to select a string value or an array of strings. The options are populated through asynchronous fetch requests.
Checkout the demo or try it out in a sandbox
Table of contents
Features
- Support for custom
fetch()
request parameters like headers, method, and body - Supports GraphQL and REST APIs
- Nested data structures
- Grouped options
- Fuzzy searching fetched options
Install
Via NPM:
npm install @adamjkb/netlify-cms-widget-async
You may install it through native JavaScript
import
through CDNs such as Skypack
import { Widget as AsyncSelectWidget } from '@adamjkb/netlify-cms-widget-async'
CMS.registerWidget(AsyncSelectWidget)
script
tag:
Via <script src='https://unpkg.com/@adamjkb/netlify-cms-widget-select-async/dist/index.umd.js'></script>
<script>
CMS.registerWidget(AsyncSelectWidget.Widget)
</script>
How to use
Simple usage
Add to your NetlifyCMS collection:
fields:
- name: simple_usage
label: Simple usage
widget: select-async
# widget options:
url: https://fakestoreapi.com/products
value_field: id
display_field: title
Advanced usage
Add to your NetlifyCMS collection:
fields:
- name: advanced_usage
label: Advanced usage
widget: select-async
# widget options:
url: https://graphql.myshopify.com/api/graphql
value_field: node.value
display_field: node.label
data_path: data.products.edges
grouped_options:
data_path: node.options.edges
value_field: node.id
display_field: node.title
multiple: true
min: 1
max: 4
refetch_url: false
fuzzy_search: true
fetch_options:
headers:
Content-Type: application/json
X-Shopify-Storefront-Access-Token: dd4d4dc146542ba7763305d71d1b3d38
method: POST
body: '{"query": "query allProducts{ products(first:10) { edges { node { label: title value: id options: variants(first:3) { edges { node { id title } } } } } } }"}'
Options
url
string
Endpoint URL
Example: https://fakestoreapi.com/products
display_field
string | default: "label"
Object key or path to object to be displayed.
Example: node.label
or title
value_field
string | default: "value"
Object key or path to object to be saved.
Example: node.value
or id
data_path
string?
Object key or path to object to the array of objects to be used as options.
If fetch()
request does not return an array of object but an object this value can be used to access the array.
Example: data.products.edges
or data
multiple
boolean | default: false
Allows multiple options to be selected. Widget's output value is going to change to an string[]
min
and max
integer?
Minimum and maximum number of items allowed to be selected
ignored if
multiple
is false
fetch_options
object?
The properties of this field are mapping to the main values of native fetch()
request parameters. fetch()
documentation on MDN
If you need to set parameters outside of the built-in
method
,headers
, andbody
you can do so with by extending the passed in parameters using thefethc_options.params_function
fetch_options.method
string | default: "GET"
Request method.
fetch_options.headers
object | default: {}
Request headers.
Example:
fetch_options:
headers:
Content-Type: application/json
X-Access-Token: <PUBLIC-API-KEY>
fetch_options.body
string | default: undefined
Request body.
Note that GET methods does not have a body. Change request method if you are specifying this field.
fetch_options.params_function
function?
⚠️ Only works if you are using a JavaScript config file to initialize NetlifyCMS. Refer to documentation how to set that up.
A JavaScript function that receives all all the other fetch_options
values, the url
, and the search input term. Must return a valid object with at least a url property.
function({term, url, method, headers, body}) {
// ...
return {
url, // required
options: {method, headers, body} // optional
}
}
Example config using a GraphQL query with variables:
fetch_options: {
// ...
params_function: ({ term, url, ...rest }) => ({
url,
options: {
...rest,
body: JSON.stringify({
query: `
query allProducts(
$myCustomQuery: String
) {
products(
first: 15
query: $myCustomQuery
) {
edges {
node {
label: title
value: id
}
}
}
}
`,
variables: {
'myCustomQuery': `title:${term}*`
}
})
}
})
}
grouped_options
object?
If you have data structure where there is a second level of option you have the option to group them together. A sample data structure:
const data = [
{
label: 'Colors',
options: [
{
label: 'Red',
value: 'red'
},
// ...
]
},
{
label: 'Flavors',
options: [
{
label: 'Salted Caramel',
value: 'salted-caramel'
}
// ...
]
},
// ...
]
grouped_options.display_field
string | default: "label"
Object key or path to object to be displayed.
grouped_options.value_field
string | default: "value"
Object key or path to object to be saved.
grouped_options.data_path
string
Object key or path to object to the array of objects to be used as options.
refetch_url
boolean | default: true
By default react-select
will send a try to load new options through a new request whenever the search input changes, setting this field's value to false
will prevent that and retain the options after the initial request.
Note that the fetched options are filtered with fuzzy search by default so the search input will affect the displayed options.
fuzzy_search
boolean | default: true
The widget uses fuse.js
to search the provided options. But if you are using filtering the data on the API level you might not want to filter the result on client side too. See fetch_options.params_function
Setting both
fuzzy_search
andrefetch_url
off will turn off input field search function.
Authors
Acknowledgments
The project was heavily inspired by @chrisboustead's asynchronous implementation of the original NetlifyCMS Select widget, netlify-cms-widget-select-async