Injecting List, Show, Edit, Create in any places - react-admin

I would like create a file browser with <List /> component in <Show /> component.
Let's say we have a user with home directory and we want to create a file browser to this directory with ability to remove files. The idea of files doesn't match the idea of simple tables, which rows can be edited.
So I have created my own component with username and directory as states, useDataprovider() as hook, and <Table/> from MUI, altered data provider a bit. And it works quite nice.
The problem comes when there are many position in list, like 50+. A pagination would be nice. So I tried to fake props of <List /> and later <ListView /> to replace <Table /> but I failed.
After short code review, it looks like implementing <List /> as is, is not possible, because many hooks and other things it uses. In general nesting one into another of any type would be a mess in come.
My idea of this would look like this:
function HomedirBrowser({username}) {
const [usrPath, setUsrPath] = React.useState("/");
return (<List
resource={`/users/${username}/dir/${usrPath}`}
>
<Datagrid>
<TextField source="type"/>
<TextField source="name"/>
<TextField source="last_edit"/>
<TextField source="size"/>
<Button onClick={({record}) => setUsrPath(usrPath + "/" + record.name)}>Enter</Button>
</Datagrid>
</List>)
}
The custom resource which would depend on a state and the button could alter the state.
Is this possible to do? Or there is any other way to achieve nesting one element into another.
Of course, I don't want to save state to browsing in url of anywhere at all.

I had a similar problem. I wanted to place a List component inside a Show component. Here is an example what I wanted to achieve:
const AuthorShow = props => (
<Show {...props}>
<TabbedShowLayout>
<Tab label='author'>
<TextField source="firstName"/>
<TextField source="lastName"/>
</Tab>
<Tab label='books'>
<List {...props}
resource='books'
filter={{authorId: props.id}}>
<Datagrid>
<TextField source="title" />
</Datagrid>
</List>
</Tab>
</TabbedShowLayout>
</Show>)
Although I explicitly passed 'resource' prop, it was ignored and Show resource was used - authors. I managed to fix this behavior by wrapping List in a Fragment.
const AuthorShow = props => (
<Show {...props}>
<TabbedShowLayout>
<Tab label='author'>
<TextField source="firstName"/>
<TextField source="lastName"/>
</Tab>
<Tab label='books'>
<Fragment>
<List {...props}
resource='books'
filter={{authorId: props.id}}>
<Datagrid>
<TextField source="title" />
</Datagrid>
</List>
</Fragment>
</Tab>
</TabbedShowLayout>
</Show>)
I don't know what caused that you failed to use List but this one may give you some clue at least.

I have the similar code:
<Fragment>
<List
{...props}
resource="card_program_options"
filterDefaultValues={{ card_id: 1 }}
sort={{ field: "id", order: "ASC" }}
>
<Datagrid>
<TextField source="card_id" />
<TextField source="card_programs_id" />
</Datagrid>
</List>
</Fragment>
But the only thing i see on the page is No results found
screenshot of No results found in show
I see the request made in the backend and completes with a 200 response code.
Help is appreciated!

Related

React admin custom component inside simpleform

Hello stackoverflow so I have a custom components inside of my create simpleform looking like this.
<Create {...props}>
<SimpleForm {...props}>
<TextField id="standard-basic" onChange={onChangeLabel} value={entityLabel} placeholder="Audience label" />
<br />
<EntityInput onSelectEntity={addEntity} entityNames={entityNames} />
<TagInput setSelectedTags={addSelectedTag} selectedTags={selectedTags} />
<br />
</SimpleForm>
</Create>
My question is how do I enable the save button and pass in custom data and tell the save button which records to create?

How to make a full width render on ReferenceManyField?

I have a react-admin show page configured with some ReferenceManyField components like this one:
<ReferenceManyField
reference="children"
target="userId"
label="Enfants"
>
<Datagrid
rowClick="edit"
>
<TextField
source="lastName"
label="Nom"
/>
<TextField
source="firstName"
label="Prénom"
/>
<DateField
source="birthday"
label="Date de naissance"
showTime={false}
/>
<TextField
source="phoneNumber"
label="Tél."
/>
</Datagrid>
</ReferenceManyField>
It works, but the rendered tab are content sized:
My question is quite simple: How to make it full width?
I tried the fullWidth option on ReferenceManyField without any effect.

Can't get ReferenceManyField to display data

Have spent several hours trying to get ReferenceManyField to display some data in a nested DataGrid.
<Show {...this.props}>
<SimpleShowLayout>
<TextField source="id" />
<TextField source="name" />
{/* THE FOLLOWING COMPONENT DOES NOT DISPLAY ANY DATA. WHY NOT??? */}
<ReferenceManyField label="Stores" reference="stores" target="companies_id">
<Datagrid rowClick="show">
<TextField source="id" />
<TextField source="storeName" />
</Datagrid>
</ReferenceManyField>
</SimpleShowLayout>
</Show>
I have created a massively stripped down version of my app, which demonstrates the problem:
https://codesandbox.io/s/react-admin-referencemanyfield-issue-forked-lde6c
I am certain there has to be a simple explanation for this issue, but as a relative newcomer to React/ReactAdmin/Typescript I just can't see it. What am I doing wrong?
Grateful for any tips & advice.
You haven't declared the stores resource in your Admin component.
Add a <Resource name="stores" /> inside Admin

Use a ReferenceField inside of an ArrayInput/SimpleFormIterator

As the title says. I need to use a ReferenceField inside of a ArrayInput/SimpleFormIterator. I keep getting the following error:
TypeError: Cannot read property 'replace' of undefined
Versions:
react-admin: 3.2.3
react: 16.12.0
Here is a snippet of the code:
<ArrayInput source="specialties" label="">
<SimpleFormIterator disableAdd>
<ReferenceField label="Specialties Link" source="ID" reference="specialty" link="show" >
<TextField source="ID" />
</ReferenceField>
<TextInput source="vendorSpecialtyText" label="Vendor Specialty Text" />
</SimpleFormIterator>
</ArrayInput>
There is a resource called specialty and this works inside of an ArrayField in other parts of the application like so:
<ArrayField source="specialties" label=" Specialties">
<SingleFieldList>
<ReferenceField label="Specialties Link" source="ID" reference="specialty" link="show" >
<TextField source="ID" />
</ReferenceField>
</SingleFieldList>
</ArrayField>
Not sure if this just isn't possible within this framework or if I'm implementing this wrong. If there is a way to fix this or a different want to go about this please let me know! Thanks.
From the documentation:
Note: SimpleFormIterator only accepts Input components as children. If you want to use some Fields instead, you have to use a <FormDataConsumer> to get the correct source,..."
import { ArrayInput, SimpleFormIterator, DateInput, TextInput, FormDataConsumer } from 'react-admin';
<ArrayInput source="backlinks">
<SimpleFormIterator disableRemove >
<DateInput source="date" />
<FormDataConsumer>
{({ getSource, scopedFormData }) => {
return (
<TextField
source={getSource('url')}
record={scopedFormData}
/>
);
}}
</FormDataConsumer>
</SimpleFormIterator>
</ArrayInput>
or include input fields
<ArrayInput source="specialties" label="">
<SimpleFormIterator disableAdd>
<ReferenceInput label="Specialties Link" source="ID" reference="specialty">
<SelectInput optionText="{Your description field}" />
</ReferenceInput>
<TextInput source="vendorSpecialtyText" label="Vendor Specialty Text" />
</SimpleFormIterator>
</ArrayInput>

Get data from a custom endpoint in react-admin

I'm using react-admin with data that I get from a restAPI data source that I can customize for my needs, I've added a standard resource with only a list and an edit attributes:
<Resource name="topic" edit={TopicsEdit} list={TopicsList} />
When I look at the network tab of Chrome dev tools I see that I use the right endpoints:
For the list:
GET request for http://api.loc/topic
And for the edit:
GET request for http://api.loc/topic/{{topic_id}}
Up to this point everything works just fine.
My problem starts when I try to have the edit screen split into two tabs, one of them will be for editing the topic (This works just fine), and the other tab should use data from a different endpoint:
http://api.loc/topic/{{topic_id}}/modifiers
The code for my TopicsEdit file:
<Show {...props}>
<TabbedShowLayout>
<Tab label='topic'>
<Edit {...props}>
<SimpleForm>
<TextInput source="id"/>
<TextInput source="title"/>
</SimpleForm>
</Edit>
</Tab>
<Tab label='modifiers' path='modifiers'>
<List {...props}>
<Datagrid>
<TextField source="id"/>
<TextField source="name"/>
</Datagrid>
</List>
</Tab>
</TabbedShowLayout>
</Show>
In the topic tab everything is working as I mentioned before, but when I switch to the modifiers tab I see in the network dev tool that the data arrives from
http://api.loc/topic
instead of
http://api.loc/topic/{{topic_id}}/modifiers
How can I customize the URL that the modifiers tab will pull the data from?
The only thing I did find was to use a <ReferenceInput> but the problem here is that the reference="" attribute will only get the info from a predefined structure, meaning that if I use reference="modifiers" it tries to fetch the data from:
http://api.loc/modifiers
And not from the desired URL.