How to connect EditorJS in admiral
10 minutes
Tools
Admiral
Backend
Frontend
Jun 3, 2025
5 minutes
public function ajaxSelect(Request $request, $field, RecordValues $values)
{
return match ($field) {
'client_id' => $values->clients($request->input('query'), $request->input('location_id')),
'location_id' => $values->locations($request->input('query')),
'services' => $values->services($request->input('query'), $request->input('location_id'), $request->input('master_id')),
'master_id' => $values->masters($request->input('query'), $request->input('location_id')),
default => collect(),
};
}
public function clients(string $query, int $locationId)
{
return Client::query()
->when($query, fn ($q) => $q->where('name', 'ilike', "%{$query}%"))
->where('location_id', $locationId)
->limit(20)
->get(['id', 'first_name', 'last_name'])
->map(fn (Client $client) => [
'value' => $client->id,
'label' => $client->full_name,
]);
}
export const CRUD = createCRUD({
path: '/records',
resource: 'records',
form: {
create: {
fields: <RecordsFields />,
},
edit: {
fields: <RecordsFields />,
},
},
})
import React from 'react'
import { AjaxSelectInput, FieldValues, useForm, useUpdateEffect } from '@devfamily/admiral'
import api from '@/src/config/api'
const resource = 'records'
const RecordsFields = () => {
const { values, setValues, setOptions } = useForm()
useUpdateEffect(() => {
setValues((prevValues: FieldValues) => ({
...prevValues,
// Reset the selected master when you change the location.
client_id: null,
}))
const fetchOptions = async () => {
if (!values.location_id) return
try {
const clientOptions = await api.getAjaxSelectOptions(resource, 'client_id', {
location_id: values.location_id,
})
setOptions((prevOptions: FieldValues) => ({
...prevOptions,
client_id: clientOptions,
}))
} catch (error) {
console.error('Failed to fetch options:', error)
}
}
fetchOptions()
// When the location ID appears in the form, this hook is triggered and then the data is fetched to get the list of clients.
}, [values.location_id])
return (
<>
<AjaxSelectInput
label="Location"
name="location_id"
placeholder="Location"
required
allowClear
fetchOptions={(field, query) =>
api.getAjaxSelectOptions(resource, field, {
query,
})
}
/>
<AjaxSelectInput
label="Client"
name="client_id"
placeholder="Client"
required
allowClear
fetchOptions={(field, query) => {
return api.getAjaxSelectOptions(resource, field, {
query,
location_id: values.location_id,
})
}}
// The field will be locked until we select the locations in the top box.
disabled={!values.location_id}
/>
</>
)
}
//The wrapper is needed so that useUpdateEffect is not triggered after the form is initialized.
const RecordsFieldsWrapper = () => {
const { options } = useForm()
return !!Object.keys(options).length ? <RecordsFields /> : <>
}
export default RecordsFieldsWrapper