I wanted to the same thing and managed (more or less). I'm not entirely happy with the solution mainly because I need specify an initial state for <Admin />
. This is needed, because if I access the child URL directly, the AOR/DECLARE_RESOURCES
action doesn't finish on time and I have an empty state for the parent and the child. (any pointers would be much appreciated why is this happening)
I have a model called providers and one can upload multiple images for a provider.
You can find descriptions on the how and why in the code sample.
I hope this helps you.
// ProviderPhoto Components
export const ProviderPhotoList = (props) => (
// have to pass in the resource here otherwise this would be done by <CrudRoute /> but in our case
// the <Create> and the <List> is not the child of <Resource />
// also hasCreate=true because we want to show the new image button and filter is hardcoded with the providerId coming from the route (see below)
<List {...props} resource="provider-photos" perPage={25} hasCreate={true} filter={{ provider: props.providerId }}>
<ProviderPhotoGrid />
</List>
)
export const ProviderPhotoCreate = (props) => (
// have to pass in the resource here otherwise this would be done by <CrudRoute /> but in our case
// the <Create> and the <List> is not the child of <Resource />
<Create resource="provider-photos" {...props}>
<SimpleForm>
<ReferenceInput source="provider" allowEmpty reference="providers" validate={ required } defaultValue={props.providerId}>
<SelectInput optionText="name" />
</ReferenceInput>
<ImageInput source="photos" accept="image/*" maxSize={10*1024*1024} multiple>
<ImageField source="src" title="" validate={ required }/>
</ImageInput>
</SimpleForm>
</Create>
)
// customRoutes.js
import { Route } from 'react-router-dom';
export default [
// few things to note here:
// - using render instead of component, otherwise the component gets created too early
// - passing in the provider (parent) ID from the route params
// - passing in ...routeProps (List Create Edit needs it)
<Route exact path="/providers/:providerId/provider-photos" render={(routeProps) => <ProviderPhotoList providerId={routeProps.match.params.providerId} {...routeProps}/>} />,
<Route exact path="/providers/:providerId/provider-photos/create" render={(routeProps) => <ProviderPhotoCreate providerId={routeProps.match.params.providerId} {...routeProps}/>} />,
];
// App.js
// hacky :(
const initialState = {
admin: {
resources: {
'providers': { props: { name: 'providers' }, data: {}, list: { ids: [], params: { sort: null, order: null, page: 1, perPage: null, filter: {} }, total: 0 } },
'provider-photos': { props: { name: 'provider-photos' }, data: {}, list: { ids: [], params: { sort: null, order: null, page: 1, perPage: null, filter: {} }, total: 0 } }
}
}
};
const App = () => (
<Admin customRoutes={customRoutes} restClient={restClient} initialState={initialState}>
<Resource name="providers" list={ProviderList} create={ProviderCreate} edit={ProviderEdit} remove={Delete} />
{/* no list,create,edit etc... specified, we just register the resource */}
<Resource name="provider-photos"/>
</Admin>
);