In React-Admin, could I disable the mailto link created by EmailField? - react-admin

I'm setting an admin panel and listing the users that are registered in a platform.
In the listing page, when I click over the row I am linked to edit page. However, one of the fields is 'email' and I use EmailField to get advantage of validations, what it automatically creates an anchor tag with a mailto functionality.
For all the fields I am showing, 'email' is the unique field that has a link so, from the UX point of view, it invites to click it. And when I click over the link, the email client is opened. That is why I want to disable the link.
I could change to TextField, but I want to keep EmailField's validations. So, is there a way to avoid creating a mailto anchor over the email? I can't find it in the docs or in google.
export const UserList = props => (
<List bulkActionButtons={false} {...props} filters=
{<UserFilter/>} perPage={10} sort={{ field: 'email', order: 'ASC'
}} pagination={<UserPagination />} >
<Datagrid rowClick="edit">
<EmailField source="email" />
<BooleanField source="isAdmin" />
<EditButton />
<DeleteButton />
</Datagrid>
</List>
);
Thanks for your help.

Related

How to add a click handler to Fluent UI v9's SplitButton?

The documentation of Fluent UI v9's SplitButton is not clear on how to add a click handler to the primary button.
Can anyone show me an example of how that is done?
I have tried finding examples on their GitHub page and I've googled for possible examples and I found one GitHub issue noting that this is a problem with their documentation.
Figured it out:
<Menu positioning="below-end">
<MenuTrigger disableButtonEnhancement>
{(triggerProps: MenuButtonProps) => (
<SplitButton
primaryActionButton={{ onClick: handleClick }}
menuButton={triggerProps}
>
Example
</SplitButton>
)}
</MenuTrigger>
<MenuPopover>
<MenuList>
<MenuItem>
Remove file
</MenuItem>
</MenuList>
</MenuPopover>
</Menu>

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?

Is it possible to fill in SearchInput with data from current endpoint?

React-admin documentation suggests to filter data via referencing to another endpoint like:
<Filter {...props}>
<TextInput label="Search" source="q" alwaysOn />
<ReferenceInput
label="User"
source="userId"
reference="users"
allowEmpty
>
<SelectInput optionText="name" />
</ReferenceInput>
</Filter>
But in my case there is no need to refer to another endpoint and I would like to filter current list relying on data from this list:
<Filter {...props}>
<SelectInput label='Title' source='Title' allowEmpty/>
</Filter>
But the filter list is empty. How can I data from "title"? I will be grateful for any possible help.
Using the ReferenceInput will set the choices property of the SelectInput. If you want to use the SelectInput alone, you need to provide a choices property by yourself like
<SelectInput
choices={items.map(({ id, name }) => ({
id,
name
}))}
label="My Select"
source="userId"
/>

Injecting List, Show, Edit, Create in any places

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!

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.