Cutomize Delete button react-admin - reactjs

Is there any way to customise DeleteButton button in react-admin to add a confirmation message like 'Do you want to delete item?'. Currently on clicking on DeleteButton it directly deletes the item without asking for a confirmation. I tried adding title attribute to delete button but it does not get fired.
Here is my code
//This worked with admin-on-rest, but not working with react-admin
const CategoryDeleteTitle = translate(({ record, translate }) => <span>
{translate('Delete')}
{record && `${record.code} ${record.name}`}
</span>);
const EditActions = ({ basePath, data, resource }) => (
<CardActions>
<ShowButton basePath={basePath} record={data} />
<ListButton basePath={basePath} />
<DeleteButton title={<CategoryTitle />} basePath={basePath} record={data} resource={resource} />
</CardActions>
);
export const CategoryEdit = (props) => (
<Edit actions={<EditActions />} title={<CategoryTitle />} {...props}>
<SimpleForm>
<DisabledInput source="id" />
<TextInput source="name" />
</SimpleForm>
</Edit>
);

We now handle deletions in an optimistic way, providing an undo mechanism instead of a confirmation dialog.
If this doesn't suit you, you can follow the UPGRADE GUIDE which leads to this page of the documentation: https://marmelab.com/react-admin/CreateEdit.html#actions
Note that you'll have to create and handle your confirmation dialog using something like react-modals and dispatch the DELETE action yourself.

You can use this gist with custom actions like:
const UserEditActions = ({ basePath, data, resource }) => (
<CardActions>
<ListButton basePath={basePath} />
<DeleteButtonWithConfirmation basePath={basePath} record={data} resource={resource} undoable={false} />
<RefreshButton />
</CardActions>
);
export const UserEdit = ({ ...props }) => (
<Edit {...props} actions={<UserEditActions />} >
<CreateEditForm title={<EntityTitle label="User" />} />
</Edit>
);

In react-admin v3, there is now a DeleteWithConfirmButton :-)

According to the documentation "https://marmelab.com/react-admin/CreateEdit.html" create:
const CustomToolbar = props => (
<Toolbar {...props} classes={useStyles()}>
<SaveButton />
<DeleteButton undoable={false} />
</Toolbar>
);
import from react-admin button you need like this:
import {
Toolbar,
SaveButton,
DeleteWithConfirmButton
} from 'react-admin';
see all available names here https://github.com/marmelab/react-admin/tree/master/packages/ra-ui-materialui/src/button, and change DeleteButton on ImportedButton like this:
export const CustomToolbar = props => (
<Toolbar {...props} classes={useStyles()}>
<SaveButton/>
<DeleteWithConfirmButton/>
</Toolbar>
);
And change in the code, where you need <SimpleForm toolbar={<CustomToolbar />}>.

Related

React Admin: How to run method before return <Edit> form view

Im making app in React-Admin Framework. Now I am creating the edit form:
<Resource name="order" edit={OrderEdit} />
And I want to decide whether to show Edit View based on a record.
E.g If record 'id' from data provider is equal to 5, display an alert and redirect to the main view '/orders':
const OrderEdit = (props) => {
const checkId = (id) => {
if(id==5){
alert('You cannot edit an order where ID Input is 5');
useRedirect('/orders');
}
}
//checkId(this.props.record.id); <=== HERE IS MY PROBLEM
/*
1. this.props.record.id = undefined;
2. props.record.id = undefined;
3. record.id = undefined;
*/
return (
<Edit {...props} >
<SimpleForm>
<TextInput
source="id"
label="ID Input"
/>
</SimpleForm>
</Edit>
);
};
export default OrderEdit;
But I don't know how to access record.id before return.
I know that I can do it with FunctionField:
<FunctionField
render={(record) =>{
if(record) checkId(record.id)
return null;
}}
label="test"
/>
But it doesn't look right.
You do not need this. since its a functional component where you pass props as an argument.
You could return null if record.id is not the correct, which is the same way as saying display nothing:
if (checkId(this.props.record.id)) return null
return (
<Edit {...props} >
<SimpleForm>
<TextInput
source="id"
label="ID Input"
/>
</SimpleForm>
</Edit>
);
Or more clean:
return checkId(this.props.record.id) ? null : (
<Edit {...props} >
<SimpleForm>
<TextInput
source="id"
label="ID Input"
/>
</SimpleForm>
</Edit>
);
I don't know if you can access the record in the Edit view component because it calls a getOne internally and forward the record to its child. So you can eventually wrap your form to access it like:
const WrapperForm = (props) => {
const {record} = props;
return (
<SimpleForm {...props}>
<TextInput source="id" label="ID Input"/>
</SimpleForm>
);
}

Conditionally render TextFields in react-admin [duplicate]

Some fields I want to only show if they have a value. I would expect to do this like so:
<Show {...props} >
<SimpleShowLayout>
{ props.record.id ? <TextField source="id" />: null }
</SimpleShowLayout>
</Show>
But that doesn't work. I can make it somewhat work by making each field a higher order component, but I wanted to do something cleaner. Here's the HOC method I have:
const exists = WrappedComponent => props => props.record[props.source] ?
<WrappedComponent {...props} />: null;
const ExistsTextField = exists(TextField);
// then in the component:
<Show {...props} >
<SimpleShowLayout>
<ExistsTextField source="id" />
</SimpleShowLayout>
</Show>
This correctly shows the value, but strips the label.
We need to update our documentation about this. In the mean time, you can find informations about how to achieve that in the upgrade guide: https://github.com/marmelab/react-admin/blob/master/UPGRADE.md#aor-dependent-input-was-removed
Here's an example:
import { ShowController, ShowView, SimpleShowLayout, TextField } from 'react-admin';
const UserShow = props => (
<ShowController {...props}>
{controllerProps =>
<ShowView {...props} {...controllerProps}>
<SimpleShowLayout>
<TextField source="username" />
{controllerProps.record && controllerProps.record.hasEmail &&
<TextField source="email" />
}
</SimpleShowLayout>
</ShowView>
}
</ShowController>
);
Maybe this way can be useful
import { FormDataConsumer } from 'react-admin'
<FormDataConsumer>
{
({ formData, ...rest}) => formData.id &&
<>
<ExistsTextField source="id" />
</>
}
</FormDataConsumer>

how to get data from form to redirect SimpleForm edit

I have a react component below. and I want to redirect with the dataset response from dataset_id. How to i get the data to put into the redirect field for simple form ?
export const qnaEdit = props => {
return (
<Edit {...props}>
<SimpleForm
redirect="data_sets">
<TextInput disabled source="id" />
<TextInput datasetid="dataset_id" />
<TextInput source="question" />
<TextInput multiline source="short_answer" />
{/* <RichTextField multiline source="url" /> */}
</SimpleForm>
</Edit>
);}
RedirectTo can be a function, not only string, so it should help.
if (typeof redirectTo === 'function') {
return redirectTo(basePath, id, data);
}
https://github.com/marmelab/react-admin/blob/master/packages/ra-core/src/util/resolveRedirectTo.ts
Documentation: https://marmelab.com/react-admin/CreateEdit.html#redirection-after-submission
You can also pass a custom route (e.g. “/home”) or a function as redirect prop value. For example, if you want to redirect to a page related to the current object:
// redirect to the related Author show page
const redirect = (basePath, id, data) => `/author/${data.author_id}/show`;
export const PostEdit = (props) => {
<Edit {...props}>
<SimpleForm redirect={redirect}>
...
</SimpleForm>
</Edit>
);
This affects both

Displaying Menu List depending on the user permissions

I am getting the same menu list for all users when I log in. But, I need to display different menu item for different users based on their roles using react-admin.
const cardActionStyle = {
zIndex: 2,
display: 'inline-block',
float: 'right',
};
const PostShowActions = ({ permissions, basePath, data, resource }) => (
<CardActions style={cardActionStyle}>
<EditButton basePath={basePath} record={data} />
{permissions === 'admin' &&
<DeleteButton basePath={basePath} record={data} resource={resource} />
}
</CardActions>
);
export const PostShow = ({ permissions, ...props }) => (
<Show actions={<PostShowActions permissions={permissions} />} {...props}>
<SimpleShowLayout>
<TextField source="title" />
<RichTextField source="body" />
{permissions === 'admin' &&
<NumberField source="nb_views" />
}
</SimpleShowLayout>
</Show>
);
Change the component function to be able to console log the permission prop, like
const Component = ({permissions, ...props}) => {
console.log("permissions", permissions)
return <YourComponentRendering/>
}
If permissions object is undefined, you can import <WithPermissions> from React-Admin in order to have permissions prop on you component. Check Authorization for more information.

undefined id at edit page in react admin

I'm using react admin for a project, I need to add descriptions to users: admins are allowed to add/edit to any user and only user themselves can edit their own description. I am able to show the edit button to the logged in user, but every time it hits the actual edit page, the user id becomes undefined and it routes me to a bad url error page. I'm new to react and react-admin so I don't really understand what's causing it become undefined.
Thanks in advance!
//in userList.js
export const UserList = ({ permissions, ...props }) => (
<List {...props} bulkActionButtons={false} sort={{ field: 'display_name', order: 'ASC'}} >
<Datagrid>
<TextField source="display_name" label="User Name" />
<RoleField source="role" label="User Role" />
<TextField source="description" label="Description"/>
<BooleanField source="active" />
<FormDataConsumer>
{({ formData }) => (formData.id === JSON.parse(user_info).id) &&
<EditButton/>
}
</FormDataConsumer>
{permissions === "administrator" &&<EditButton />}
</Datagrid>
</List>
);
//in useredit.js
export const UserEdit = ({permissions, ...props}) => (
<Edit {...props}>
<SimpleForm toolbar={<SaveOnlyToolbar />}>
<DisabledInput source="display_name" />
<DisabledInput source="distinguished_names" />
<TextInput resource="description" label="Description"/>
<FormDataConsumer>
{({ formData }) => formData.is_only_admin ?
<React.Fragment>
<DisabledInput source="role" />
<DisabledInput source="active" />
</React.Fragment>
:
<React.Fragment>
<SelectInput source="role" label="Role" choices={RoleChoices}/>
<BooleanInput source="active" />
</React.Fragment>
}
</FormDataConsumer>
</SimpleForm>
</Edit>
);
//in app.js
const content = () => {
return (
<Admin
authProvider={authProvider}
dataProvider={dataProvider}
customRoutes={[
<Route exact path="/help" component={Help}/>,
<Route exact path="/" component={Dashboard}/>]}
loginPage={false}
>
{role => [
(role === 'administrator' || role === 'read_only' || role === 'user') ? <Resource name='user' list={UserList} icon={PeopleIcon} edit={role === 'administrator' || role === 'user' ? UserEdit : null}/> : null,
]}
</Admin>
);
}
return <>{content()}</>;
};
export default App;
The <FormDataConsumer>component works only inside forms: <SimpleForm>, <TabbedForm> and others. In the <List>component will not work.

Resources