Let's jump right in and start building a custom select field that you can use in Payload.
The standard select field allows you to choose from multiple options, and these options are predefined and passed directly to the select field.
What we're going to build is a select field that looks and works the same but has its options imported from an external source.
This can help you integrate data from a third party. For example, it might be a list of form IDs or product IDs. It's also really useful when you need to display large, universal data such as countries or national holidays.
First, we want to define our base field.
Although we're building a select component, it's important to note that we won't be using the select type. The select type field's underlying structure is an enum and must be predefined. Since this custom field will use external options, that approach won't work.
Instead, we're going to use the type text
. Then we want to override the front-end field. To do this, we'll pass in our own component to the admin components field.
Now, let's get into the custom component.
Essentially, what we're doing here is replicating the existing Payload select field and then passing in our own options – simple as that!
The first thing we're going to do is import the existing select component directly from Payload. After that, we'll want to output this component ourselves.
The select component will require the path
, name
, your options
, and value
.
We can also import the useField
function from Payload, which will help us get and set the value
.
The field path can be de-structured directly off the component and then passed in to our useField
function. From that function, we can de-structure value
and also a setValue
function.
So, if you go and take another look, you can see where the path is coming from, along with the value and setValue.
Now onto our options.
The first thing we want to do is define an empty state. Then, we come down to our fetchOptions
async function.
Essentially, what this function needs to do is pull in your data and then restructure the shape of data so that you can output it as an array of objects, each with a label and a value.
To start, it's making a fetch request to the restcountries.com API, and then we wait for that response to be converted into JSON.
Next, we're going to map over that JSON data and return a label and value for each country.
Now, we're back to the useState
setOptions function.
Within the function, I've added a couple lines of code to put the countries in alphabetical order. But essentially, we're just setting those options back into our options state
.
It's also important that we wrap all of this in a try
catch
so that if anything goes wrong, we won't break the whole admin panel.
Finally, we only want to run this function once. So, we're running this function inside of a useEffect
with no dependencies, which means this will only run once when the component initially mounts.
One last tip: you can add the class name field-label
, and Payload will automatically apply styles to this so that it matches everything else.
And that is it!
Earlier, we talked about a regular select, and now appearing just the same is our nice, new custom select with all the countries - and if take a look at the data, you will see the new `customField` and its value.
Here is a link to the GitHub repo containing this code .
If you have any questions, be sure to join us on Discord!