i have a problem i cannot solve, and i think im following the documentation to the letter.
I want to obtain the assigned roles when im editing the user, for example if exist a user "Daniel", which has "Administrator" and "Editor" roles. When im editing that user i would like to obtain those assigned roles.
my code is:
export const UserEdit = props => (
<Edit title={<RoleTitle />} {...props}>
<SimpleForm validate={validateUserEdition}>
<TextInput source="name" />
<TextInput source="email" type="email" />
<TextInput source="password" type="password" />
<ReferenceInput label="Role" source="role" reference="role">
<AutocompleteArrayInput source="id" {...props} />
</ReferenceInput>
</SimpleForm>
</Edit>
);
Add the endpoint format where check my API:
GET to /user/{user}/role
someone help me with this please?
Here's what the react-admin say:
You must add a for the reference resource - react-admin needs it to fetch the reference data.
So in your case, the <Admin/> component should at least have these:
<Admin dataProvider={myDataProvider}>
<Resource name="users" /> // endpoint that handles user records
<Resource name="roles" /> // endpoint that handles user ROLES records
</Admin>
Am not sure how you are using this endpoint /user/{user}/role but it clearly will not do what you want. Further reading here should help especially look at the notes added to the Reference* components.
I still cannot solve my problem, the resources that I have in my administrator are user and role, but I imagine that with those resources they are enough to have the relationship between the two.
Again, when I edit a user, I need to be able to view and edit the roles associated with it.
my code is the follow
export const UserEdit = props => (
<Edit title={<RoleTitle />} {...props}>
<SimpleForm validate={validateUserEdition}>
<TextInput source="name" />
<TextInput source="email" type="email" />
<TextInput source="password" type="password" />
<ReferenceInput label="Role" source="role" reference="role">
<AutocompleteArrayInput source="id" {...props} />
</ReferenceInput>
</SimpleForm>
</Edit>
);
in app.js
const App = ( ) => (
<Admin dashboard={ Dashboard } dataProvider={ dataProvider } authProvider={ authProvider }>
<Resource name="user" list={ UserList } create={ UserCreate } edit={ UserEdit } icon={ UserIcon }/>
<Resource name="role" list={ RoleList } create={ RoleCreate } edit={ RoleEdit } icon={ ContactsIcon }/>
</Admin>
);
Thank
Related
I think I've missed a step somewhere and I can't tell how to affect the form field widths to enable them to fill the area horizontally.
import * as React from 'react';
import {
Edit,
SimpleForm,
TextInput,
ReferenceInput,
SelectInput,
ArrayInput,
SimpleFormIterator,
} from 'react-admin';
import {RichTextInput} from 'ra-input-rich-text';
export const ProductNotesEdit = () => (
<Edit>
<SimpleForm>
<ReferenceInput source="productId" reference="products" label="Product">
<SelectInput optionText="name" />
</ReferenceInput>
<TextInput source="productId" />
<ReferenceInput source="promptId" reference="ml_prompts" label="Prompt">
<SelectInput optionText="slug" />
</ReferenceInput>
<TextInput source="promptId" />
<ArrayInput source="contextUrls">
<SimpleFormIterator>
<TextInput source="url" />
</SimpleFormIterator>
</ArrayInput>
<ArrayInput source="contextTexts">
<SimpleFormIterator>
<TextInput source="text" />
</SimpleFormIterator>
</ArrayInput>
<TextInput source="notes" multiline={true} />
</SimpleForm>
</Edit>
);
How can I increase the width of the fields?
Example form
Source
So it seems that I'm missing the fullwidth argument in my fields.
<TextInput source="notes" multiline fullWidth />
Currently, if I try to place a Field into an Edit form, the field doesn't display at all. There is no errors in the console or the terminal about why it wont.
Example:
<Edit undoable={false} {...props}>
<SimpleForm>
<FormRow>
<TextField source="id"/>
<TextField source="name"/>
</FormRow>
</SimpleForm>
</Edit>
will not display either of these on the page load, it will simply be blank.
Is there any way to use fields in the Edit form?
You need to pass in the record prop (and basePath if its a reference).
The Edit component does not get the record prop so create a form component and it will get passed the record as a prop
eg.
const ProjectEdit: FC<EditComponentProps> = props => {
const classes = useStyles();
return (
<RA.Edit {...props} title={<ProjectTitle />}>
<RA.SimpleForm>
<ProjectForm />
</RA.SimpleForm>
</RA.Edit>
);
};
export const ProjectForm = (props: any) => {
return (
<Box flex={1} mr={{ md: 0, lg: '1em' }}>
<RA.TextInput source="name" fullWidth={true} />
<Typography variant="h6" gutterBottom>
Tasks
</Typography>
<RA.TextField
source="name"
fullWidth={true}
record={props.record}
/>
<RA.ReferenceManyField
label="Tasks"
reference="Task"
target="projectId"
fullWidth={true}
record={props.record}
basePath="/Task"
>
<RA.SingleFieldList fullWidth={true}>
<RA.ChipField source="name" fullWidth={true} />
</RA.SingleFieldList>
</RA.ReferenceManyField>
</Box>
);
};
I'd like to know what are the data I'm working with, when using react-admin. (see them in the console to help debug)
For instance, when I'm working with a List:
import React from 'react';
import { Datagrid, List, TextField } from 'react-admin';
import { ListProps } from '../../types/admin/ListProps';
const ProductList = (props: ListProps): JSX.Element => {
console.log('ProductList.props', props);
return (
<List
{...props}
sort={{
field: 'titleEN',
order: 'DESC',
}}
>
<Datagrid rowClick="edit">
<TextField source="title" />
<TextField source="titleEN" label={'Title (EN)'} />
<TextField source="titleFR" label={'Title (FR)'} />
{/*<ArrayField source="images"><SingleFieldList><ChipField source="id" /></SingleFieldList></ArrayField>*/}
{/*<ReferenceArrayField source="imagesIds" reference="images"><TextField source="id" /></ReferenceArrayField>*/}
<TextField source="customer.label" label={'Customer'} />
<TextField source="price" />
</Datagrid>
</List>
);
};
export default ProductList;
How can I do that? I haven't found anything in the official doc https://marmelab.com/react-admin/List.html
This kind of logging can be displayed through the Data Provider. See https://marmelab.com/react-admin/DataProviders.html
For instance, with https://github.com/marcantoine/ra-data-graphql-prisma data provider, one such implementation could be https://github.com/UnlyEd/ra-data-graphql-prisma/commit/4031c5c3f2e97c479a9714df56da06653a908444
I'm trying to access nested values in a REST API array within the LIST VIEW of a React-Admin project. In short I'm trying to do something like "Array.item" when passing it to a component that renders it.
I've got my data populating like so:
Each messages array looks like this, so here's one of them:
for (let i = 0; i < 13; i++) {
data.messagesDirect.push({
id: i,
read: faker.random.boolean(),
date: faker.date.past(),
subject:
faker.name.jobDescriptor() +
' ' +
faker.name.jobArea() +
' ' +
faker.name.jobType(),
content: faker.lorem.paragraph(),
email:
faker.internet.email() +
' - ' +
faker.name.firstName() +
' ' +
faker.name.lastName()
});
}
And then I put them in one array in the end.
data.messages.push({
id: 0,
inbox: data.messagesInbox,
outbox: data.messagesOutbox,
direct: data.messagesDirect
});
data.messagesInbox,outbox and direct are generic arrays, they contain the same type of data.
I'm trying to access each array individually, and pass that information to be rendered by a component made to render these arrays.
export const MessagesList = props => (
<FullWidthTabs>
<List actions={<InboxListActions />} {...props}>
<MessagesGrid data="messages.inbox" />
</List>
<List actions={<OutboxListActions />} {...props}>
<MessagesGrid data="messages.outbox" />
</List>
<List actions={<DirectListActions />} {...props}>
<MessagesGrid data="messages.direct" />
</List>
</FullWidthTabs>
);
No matter what it keeps passing the context of the array as if it's only at the top level, it's never passing the exact array object I'm referencing with the "."
I am doing this wrong, and I need understanding and guidance on how to do this right.
Messages grid just expects an array to iterate through and create UI for each item.
const MessagesGrid = ({ data, basePath, resource }) =>
console.log(data) || (
<div style={{ margin: '1em' }}>
{data.map(id => (
<Card key={id} style={cardStyle}>
<ReadField record={data[id]} source="confirmed" />
<CardHeader
title={<TextField record={data[id]} source="subject" />}
subheader={<DateField record={data[id]} source="date" />}
/>
<CardContent>
<TextField record={data[id]} source="content" />
</CardContent>
...
Figured it out, doing it like this, by wrapping them in Datagrids and using ArrayField it was able to step into each array:
export const MessagesList = (props, resource) => (
<FullWidthTabs>
<List actions={<InboxListActions />} {...props}>
<Datagrid>
<ArrayField source="inbox">
<MessagesGrid />
</ArrayField>
</Datagrid>
</List>
<List actions={<OutboxListActions />} {...props}>
<Datagrid>
<ArrayField source="outbox">
<MessagesGrid />
</ArrayField>
</Datagrid>
</List>
<List actions={<DirectListActions />} {...props}>
<Datagrid>
<ArrayField source="direct">
<MessagesGrid />
</ArrayField>
</Datagrid>
</List>
</FullWidthTabs>
);
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>