Create custom form in react-admin - reactjs

I am using Edit and SimpleForm from react-admin. How do I create a custom form to allow customised action and type on submit?
App.js
<Resource name="category" list={CategoryList} edit={CategoryEdit} />
index.js
<Edit actions={<CategoryEditActions />} title={<CategoryTitle />} {...props} >
<SimpleForm>
<DisabledInput source="id" />
<DisabledInput source="code" />
<TextInput source="name" />
</SimpleForm>
Here the api call would be /category/:categoryId with PUT request. I want to modify url to /category/:categoryId/test with method as POST. Is there any way to customize this?
I have handled this in my CustomDataProvider -
case UPDATE:
if(resource === 'category'){
options.method = 'POST';
url = `${apiUrl}/${resource}/${params.id}/test`;
} else {
options.method = 'PUT';
url = `${apiUrl}/${resource}/${params.id}`;
}
break;
Is there any other way to handle it?

This is the job of your dataProvider in react-admin (restClient in admin-on-rest). You'll have to create a custom one:
For react-admin: https://marmelab.com/react-admin/DataProviders.html#writing-your-own-data-provider
For admin-on-rest: https://marmelab.com/admin-on-rest/RestClients.html#writing-your-own-rest-client
You'll have to check the resource and type then build the fetch options by yourself.

Related

React Admin - send custom query during edit/create record

I have a simple form to edit camera
export const CameraEdit: FC<ResourceComponentProps> = (props: ResourceComponentProps) => (
<Edit {...props}>
<SimpleForm>
<TextInput source="name" />
<TextInput source="connection" />
<Button variant="contained" label="Preview"></Button>
</SimpleForm>
</Edit>
);
When I click on Preview button I want to
fetch preview from backend (using GraphQL)
download the image
show it on the right side of form
I don't know how to:
issue additional async query (not related to editing data) as in normal react app I had container and component
download the image (result of query)
add additional div to SimpleForm - I've read it can handle only direct inputs

React Admin - overiding handleSubmit on SimpleForm

What I want to achieve is this but using react admin SimpleForm instead of Form:
import React, { useState } from "react";
export function NameForm(props) {
const [name, setName] = useState("");
const handleSubmit = (evt) => {
evt.preventDefault();
alert(`Submitting Name ${name}`)
}
return (
<form onSubmit={handleSubmit}>
<label>
Frirst Name:
<input
type="text"
value={name}
onChange={e => setName(e.target.value)}
/>
</label>
<input type="submit" value="Submit" />
</form>
);
}
When I try the same pattern, i.e.:
<SimpleForm onSubmit={handleSubmit}>
it never reaches the handleSubmit function. I also tried:
<SimpleForm handleSubmit={handleSubmit}>
But again no joy.
The react admin docs here say:
Finally, it receives a handleSubmit function as prop, to be called with the updated record as an argument when the user submits the form.
Unfortunately being new to react this doesn't give me any clue as to what I should do to get this to work.
When you're using any third party library you need to follow their rules. Here you're using React admin library which support normal admin features like add/edit/listing etc. With minimal effort you can create admin panel.
So when you're focusing on creating form using React Admin , you can create add/edit form.
In your App.js you need to first define routing using Resource which contains create and edit attribute. In create/edit you can import your add/edit component and pass it. The example is given below. You can see dataProvider link is also provided. When you'll create edit form it will take data from there
// in src/App.js
import * as React from "react";
import { Admin, Resource } from 'react-admin';
import jsonServerProvider from 'ra-data-json-server';
import { PostCreate, PostEdit } from './posts';
const App = () => (
<Admin dataProvider={jsonServerProvider('https://jsonplaceholder.typicode.com')}>
<Resource name="posts" create={PostCreate} edit={PostEdit} />
</Admin>
);
export default App;
After creating proper routing you can go to your component and can create add/edit form just like below
// in src/posts.js
import * as React from "react";
import { Create, Edit, SimpleForm, TextInput, DateInput, ReferenceManyField, Datagrid, TextField, DateField, EditButton } from 'react-admin';
import RichTextInput from 'ra-input-rich-text';
export const PostCreate = (props) => (
<Create {...props}>
<SimpleForm>
<TextInput source="title" />
<TextInput source="teaser" options={{ multiLine: true }} />
<RichTextInput source="body" />
<DateInput label="Publication date" source="published_at" defaultValue={new Date()} />
</SimpleForm>
</Create>
);
export const PostEdit = (props) => (
<Edit {...props}>
<SimpleForm>
<TextInput disabled label="Id" source="id" />
<TextInput source="title" validate={required()} />
<TextInput multiline source="teaser" validate={required()} />
<RichTextInput source="body" validate={required()} />
<DateInput label="Publication date" source="published_at" />
<ReferenceManyField label="Comments" reference="comments" target="post_id">
<Datagrid>
<TextField source="body" />
<DateField source="created_at" />
<EditButton />
</Datagrid>
</ReferenceManyField>
</SimpleForm>
</Edit>
);
React-admin injects a few props to the create and edit views: the resource name, the basePath (the root URL), the permissions, and, in the case of the edit view, the record id. That’s why you need to pass the props to the <Create> and <Edit> components.
The <Create> and <Edit> components call the dataProvider, prepare the form submit handler, and render the page title and actions.
<SimpleForm> Which you mentioned in your question is responsible for creating the form only, it's not responsible for handleSubmit operation , <Create> and <Edit> components handle that.
To know more in details follow the React Admin <Create> and <Edit> doc carefully.
So I found the solution I was looking for thanks to the answer from Saswata Pal. To achieve the effect I was looking for I changed the component so it was like this:
<Create transform={transform}>
This allowed me to grab the form result before submission and modify.
Relevant docs here:
https://marmelab.com/blog/2020/06/09/react-admin-3-6.html

React-admin change EditButton, get request

I am fairly new to React and react-admin. So far most of the stuff working smoothly. But I want to make the EditButton little differently that it gives.
The current request is handled like this:
localhost/api/posts/26
EditButton button called in the DataGrid like this
const PostsList = ({ permissions, ...props }) => (
<List
{...props}
filters={<PostsFilter />}
sort={{ field: 'name', order: 'ASC' }}
actions={<ActionsRefresh />}
bulkActions={false}
>
<Datagrid
{...props}
ids={this.state['clasifiers']}
hover={false}>
<TextField source="id" />
<TextField source="name" label="Name" />
<EditButton />
</Datagrid>
</List>
)
export default ClassifiersList
And the respective index.js file =>
import PostList from './PostList'
import PostEdit from './PostEdit'
export default {
list: PostList,
edit: PostEdit
}
But I want to pass more parameters to server from this get request, like:
localhost/api/posts/26/7
OR
localhost/api/posts/26?status=7
Is there a option to make the EditButton request change or do I have to create a custom button and onClick view the EditPost.js component, this I have no idea about how to do.

React-Admin: Clicking MenuItemLink for 2nd time clears form inputs

I have a react-admin based site working nicely.
Though i have an issue with the sidebar menu. If i click one of the items twice it clears all the form inputs. This is a link to an edit form of the resource item (in this case the current user profile):
<MenuItemLink to={"/users/" + user.id} primaryText="Profile" leftIcon={createElement(UserIcon)} onClick={onMenuTap}/>
with resource that looks like:
<Resource name="users" list={UserList} edit={UserEdit} create={UserCreate} icon={UserIcon} />
where UserEdit is
export const UserEdit = (props) => {
<Edit title={<UserEmail />} actions={<UserEditActions />} {...props}>
<SimpleForm validate={validateUserSave}>
<DisabledInput source="email"/>
<TextInput label="First Name" source="firstName" />
<TextInput label="Last Name" source="lastName" />
...
on first click all the inputs are populated from my REST api, but on 2nd tap (menu item selected) - all the form values are cleared...
Any ideas?
It is indeed a bug, I opened an issue on React Admin:
[#2291] Double-click on a Icon from the Menu reset the edition form
[#2322] Fix resetform when navigating to same page
A fix will be published with react-admin#2.3.2!
Thanks for reporting the issue.

admin-on-rest: customizing Edit component

I need to customize Edit component in two ways:
Add custom button, but not to the upper panel (with 'List' and
'Refresh' buttons), but at the bottom of the component (next to the default 'Save'
button).
Turn off redirect on default 'Save' button click (to make it just
save and stay on page).
How do I achieve this?
I came accross this unanswered question. Since I just did something like this very recently myself I will share how I did it here. I am using admin on rest 1.4.0 btw.
So, on your <Edit> component, add this toolbar={<MyCustomToolbar />}. Then create a custom toolbar with your buttons in it. On the button you can use redirect to redirect to another page.
Code example:
import { SaveButton, Toolbar, TextInput, Edit, SimpleForm } from 'admin-on-rest';
const MyToolbar = props =>
<Toolbar {...props} >
<SaveButton label="Save & to dashboard" redirect="/" />
.. more buttons here..
</Toolbar>;
export const EditForm = (props) => (
<Edit title="Edit" {...props}>
<SimpleForm toolbar={<MyToolbar />}>
<TextInput source="company_website" type="url" />
<TextInput source="address_street" />
<TextInput source="address_zip" />
<TextInput source="address_unitnr" />
<TextInput source="address_city" />
</SimpleForm>
</Edit>
);
Hope this helps!

Resources