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

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

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 - 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

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: 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