React Admin - overiding handleSubmit on SimpleForm - reactjs

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

Related

ReferenceManyInput in react-admin

In react-admin we have ReferenceManyField. It would be fantastic to have also a component called ReferenceManyInput, with a functionallity very similar to the ArrayInput component (add, remove buttons) but with reference to a resource.
¿Does any one know if they have intention to include it or is there any workaround to achieve this?
The use case is:
I have a form for creating/editing an entity where one of its properties is an array of other related entities. I would like to add and/or remove new elements to that array and when submitting the main entity, it creates/updates/remove the related entity and the main entity.
Maybe I am asking for too much...
Thanks in advance
You're in luck: <ReferenceManyInput> was just published as part of React-admin Enterprise Edition. It works just like ReferenceManyField:
import {
Edit,
SimpleForm,
TextInput,
NumberInput,
ReferenceInput,
SelectInput,
} from 'react-admin';
import { ReferenceManyInput } from '#react-admin/ra-relationships';
const ProductEdit = () => (
<Edit mutationMode="optimistic">
<SimpleForm>
<TextInput source="name" />
<NumberInput source="price" />
<ReferenceInput source="category_id" reference="categories" />
<ReferenceManyInput reference="variants" target="product_id">
<SimpleFormIterator inline>
<TextInput source="sku" />
<SelectInput source="size" choices={sizes} />
<SelectInput source="color" choices={colors} />
<NumberInput source="stock" defaultValue={0} />
</SimpleFormIterator>
</ReferenceManyInput>
</SimpleForm>
</Edit>
);
The result looks like:
Check https://marmelab.com/ra-enterprise/modules/ra-relationships#referencemanyinput for details.

React-admin: ReferenceInput doesn't show loading <LinearProgress> while loading possible options

I have simple react-admin edit form with ReferenceInput. The problem is that ReferenceInput never show progress bar, so it might be confusing for users to see no options while it's loading.
I manually set delay 2 seconds on API calls but ReferenceInput never show loading state.
import React from 'react';
import { ReferenceInput, ReferenceArrayInput, required, SelectArrayInput, SelectInput, SimpleForm, TextInput } from 'react-admin';
const ModelForm = props => (
<SimpleForm {...props}>
<TextInput source="name" validate={[required()]} />
<ReferenceInput reference="goods_types" source="goodsType" validate={[required()]}>
<SelectInput optionText="name" />
</ReferenceInput>
<ReferenceInput reference="manufacturers" source="manufacturer" validate={[required()]}>
<SelectInput optionText="name" />
</ReferenceInput>
<ReferenceArrayInput reference="manufacturers" source="manufacturer" format={v => [v]} validate={[required()]}>
<SelectArrayInput optionText="name" />
</ReferenceArrayInput>
</SimpleForm>
);
export default ModelForm;
Just for test I added ReferenceArrayInput component and it does show loading progress bar.
Is it bug in react-admin? Or am I missing something?
React-admin: 3.11.1
React Admin introduced a timeout with default value of 1000. The loading component only appear after this time. You can override this value by passing a prop to the component.
ref: https://github.com/marmelab/react-admin/blob/ea1f85c73f5be8f12544a0fccf32e4f6bd7452be/packages/ra-ui-materialui/src/layout/LinearProgress.tsx

How to change variant of text input in react admin

I wanted to change the variant of TextInput using material UI. The default variant is Standard and I want to change that to outlined but not able to do so. Followed documentation for material-ui Material-ui documentation
Below is my code snippet
<TabbedForm>
<FormTab label="INFO">
{/* <TextInput disabled label="" source="id" type="hidden"/> */}
<TextInput label="Name" source="name" variant="outlined"/>
<TextInput source="shortdesc" />
</FormTab>
</TabbedForm>
You need to pass in variant="standard" to the react-admin <TextInput> component. The issue is that the <Filter> and <Create> pages, etc, automatically pass in a bunch of props, like record and basePath, which includes variant: undefined for some reason. So if you just write <TextInput variant="standard" ... />, your prop will get overwritten. And then when the TextInput component passes its props to the ResettableTextField component, the now undefined variant prop gets defaulted to "filled"...
So, you just need to extract the TextInput component out, so that your variant prop comes last in the props order:
export const TextInput = props => <RaTextInput {...props} variant="standard" />
Personally, I've abstracted this all out into a HOC, because this is what you have to do for all the Inputs that use TextFields:
import React from 'react'
import {
TextInput as RaTextInput,
NumberInput as RaNumberInput,
SelectInput as RaSelectInput,
DateInput as RaDateInput,
DateTimeInput as RaDateTimeInput,
NullableBooleanInput as RaNullableBooleanInput,
AutocompleteInput as RaAutocompleteInput,
} from 'react-admin'
const standardize = Component => props => <Component {...props} variant="standard" />
export const TextInput = standardize(RaTextInput)
export const NumberInput = standardize(RaNumberInput)
export const SelectInput = standardize(RaSelectInput)
export const DateInput = standardize(RaDateInput)
export const DateTimeInput = standardize(RaDateTimeInput)
export const NullableBooleanInput = standardize(RaNullableBooleanInput)
export const AutocompleteInput = standardize(RaAutocompleteInput)
Check my code
<TabbedForm>
<FormTab label="INFO">
{/* <TextInput disabled label="" source="id" type="hidden"/> */}
<TextField label="Name" source="name" variant="outlined"/>
<TextField source="shortdesc" />
</FormTab>
</TabbedForm>
check my fork
React-admin has fixed this.
You can now use the variant="outlined | standard | filled" prop on the component enclosing the input.
Ex: SimpleForm, Create, Filter, etc.
The Git resolution

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.

Add custom column to Datagrid in admin-on-rest

I've created an admin panel in React.js using admin-on-rest. I have a page showing a user list pulling data from an api. I need to add a custom column at the end of each row of that table that will display a progress bar for each user.
I'm using a module called rc-progress to generate the progress bar. Here's an example display on a separate page currently from the user list:
import React from 'react';
import { Line } from 'rc-progress';
var Progress = React.createClass({
render: function render() {
return (
<Line percent="40" strokeWidth="1" strokeColor="#38bcd5" />
);
}
});
export default Progress;
I'm not sure how to append a custom column to a Datagrid in admin-on-rest to add in that progress bar.
Here's the code I have for the User list which is displaying the data from the API correctly. I've added a comment where I'd want to add the progress bar:
import React from 'react';
import { List, Datagrid, TextField} from 'admin-on-rest';
import { Line } from 'rc-progress';
export const UserList = (props) => (
<List {...props}>
<Datagrid>
<TextField source="firstName" />
<TextField source="lastName" />
<TextField source="email" />
<TextField source="phone" />
<TextField source="type" />
//I'd like to add the progress bar below:
//<Line percent="40" strokeWidth="1" strokeColor="#38bcd5" />
</Datagrid>
</List>
);
export default UserList;
Any help is much appreciated!
Update (Solution)
So on the recommendation of Gildas I've tried to use the FunctionField. Here is the working version of the code. (The progress bar has hard-coded values right now)
import React from 'react';
import { List, Datagrid, TextField} from 'admin-on-rest';
import { Line } from 'rc-progress';
import { FunctionField } from 'admin-on-rest'
export const UserList = (props) => (
<List {...props}>
<Datagrid>
<TextField source="firstName" />
<TextField source="lastName" />
<TextField source="email" />
<TextField source="phone" />
<TextField source="type" />
//Here is the working version below:
<FunctionField label="Progress" render= {function render() { return ( <Line percent="40" strokeWidth="1" strokeColor="#38bcd5" />);}} />
</Datagrid>
</List>
);
export default UserList;
Here's a current screenshot:
The FunctionField should do the trick: https://marmelab.com/admin-on-rest/Fields.html#functionfield
If not, have you tried following the custom field documentation ?

Resources