I am using react-admin and have incorporated the advanced tutorial "Creating and Editing a Record From the List Page". This tutorial uses react.component instead of constants. I now need to display fields based of my values in the permissions object passed by authorization. I can do this fine in constants and in the admin component but permissions is always null if I try to access it in the react.component.
class InviteCodeList extends React.Component {
render() {
const { permissions,push, classes, ...props } = this.props;
console.log('permissions');
console.log(permissions);
return (
<Fragment>
<List
{...props}
filters={<CustomFilter />}
actions={<CustomActions />}
sort={{ field: 'title', order: 'ASC' }}
>
<Datagrid>
<TextField source="id" />
<TextField source="title" />
<WithPermissions
render={({ permissions }) => (
permissions.find(f => f.resource === 'admin') !== undefined
? <TextField source="invite_code" />
: null
)}
/>
<ReferenceField source="price_list_id" reference="pricelists">
<TextField source="price_list_name" />
</ReferenceField>
<TextField source="effective_dt" />
<DateField source="expiration_dt" />
<EditButton />
</Datagrid>
</List>
Here is the new code segment. I did not check for null which is returned before the API call returns the actual data.
<Fragment>
<List
{...props}
filters={<CustomFilter />}
actions={<CustomActions />}
sort={{ field: 'title', order: 'ASC' }}
>
<Datagrid>
<TextField source="id" />
<TextField source="title" />
permissions !== null ? permissions.find(f => f.resource === 'admin') !== undefined
? <TextField source="invite_code" />
: null : null
<DateField source="expiration_dt" />
<EditButton />
</Datagrid>
</List>
Related
Hello i'm hiring for a solution my show doesn't work on the row of my table. The cursor doesn't change to let me click on a row and even if i click nothing happened. That's my code
//in App.tsx
<Admin dataProvider={DataProvider} authProvider={authProvider}>
<Resource name="users" list={UsersList} show={UserShow}/>
</Admin>
// in users.tsx
export const UsersList = () => {
// const isSmall = useMediaQuery((theme : any) => theme.breakpoints.down("sm"));
return (
<List filters={userFilters}>
<Datagrid>
<TextField source="id" />
<TextField source="firstname" />
<TextField source="lastname" />
<EmailField source="email" />
<TextField source="phone" />
<TextField source="candidatureStatus" />
<TextField source="created_at" />
</Datagrid>
</List>
);
};
export const UserShow = () => (
<Show>
<SimpleShowLayout>
<TextField label="test" source="email" />
<TextField source="firstname" />
<TextField source="lastname" />
</SimpleShowLayout>
</Show>
)
Even if i followed the tutorial on react admin i can't display a showScreen
If you want to open the Show form when clicking on a row in the List, you need to add:
<Datagrid rowClick="show">
https://marmelab.com/react-admin/Datagrid.html#rowclick
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.
I am trying to reference category in my create and edit product page. Please find the code below:
const validateProduct = (values) => {
const errors = {};
if (!values.name) {
errors.name = ['Product name is required'];
}
if (!values.category) {
errors.category = ['Product category is required'];
}
return errors
};
export const ProductCreate = (props) => (
<Create {...props}>
<SimpleForm validate={validateProduct}>
<TextInput source="name" />
<ReferenceInput label="category" source="category._id" reference="categories">
<SelectInput optionText="name" />
</ReferenceInput>
<TextInput source="price" />
<LongTextInput source="description" />
<TextInput source="image" />
</SimpleForm>
</Create>
);
const ProductTitle = ({ record }) => {
return <span>Product {record ? `"${record.name}"` : ''}</span>;
};
export const ProductEdit = (props) => (
<Edit title={<ProductTitle />} {...props}>
<SimpleForm validate={validateProduct}>
<DisabledInput source="id" />
<TextInput source="name" />
<ReferenceInput label="category" source="category._id" reference="categories">
<SelectInput optionText="name" />
</ReferenceInput>
<TextInput source="price" />
<LongTextInput source="description" />
<TextInput source="image" />
</SimpleForm>
</Edit>
);
There are few issues with the ReferenceInput:
Validation does not work for ReferenceInput.
Existing category is not selected by default in the edit product page.
I want the category validation and category selection enabled in add/edit pages. How do I achieve that in React-Admin?
Thanks
I used bulkActions props for Admin-on-rest List but don't show anything when I select rows. How to can I use the bulk action?
const AccountingBulkActions = props => (
<BulkActions {...props}>
<BulkDeleteAction />
</BulkActions>
);
export const AccountingList = (props) => (
<List
{...props}
bulkActions={<AccountingBulkActions />}
title="Accounting">
<Datagrid
headerOptions={{ adjustForCheckbox: true, displaySelectAll: true }}
bodyOptions={{ displayRowCheckbox: true }}
rowOptions={{ selectable: true }}
options={{ multiSelectable: true }}>
<DateField source="createdAt" />
<TypeLabel source="type" />
<GenderLabel source="gender" />
<NumberField source="paymentPrice" />
<NumberField source="totalPrice" />
</Datagrid>
</List>
);
Bulk actions are a new feature only available on react-admin. You'll have to upgrade your admin-in-rest app.
If I apply a filter in a List component in Admin on REST, I want to only show the filtered column (TextField) once this specific filter is selected, because the filter is fuzzy and I want to see the different results at a glance. But when no filter is set, the column is supposed to be hidden.
I implemented it like this so far.
const ConditionalFilterTextField = (props) => {
const show = ... // if filter is set in URL
return (show) ? <TextField {...props} /> : null
}
...
<List {...props} filters={<MyFilter />}>
<Datagrid>
...
<ConditionalFilterTextField sortable={false} source="filter_field" label="My Label" />
...
</Datagrid>
</List>
This does work in a way, but then again not really. It shows the label of the column and an empty space when I return null (when the filter is not set and the column is supposed to be hidden).
How can I control visibility of a TextField depending on whether a filter is set or not? How can I force a rerender of the List when I want to add a column?
Edit:
This is similar to your answer, #Gildas, but doesn't work for me. Some detail might be wrong?
in itemList.js
class ItemList extends Component {
render() {
const props = this.props
// Find out if current filter is source of field.
const filter = props.itemsFilters
const showFieldA = (filter && filter.fieldA) ? true : false
return <List {...props} filters={<ItemsFilter />} perPage={50}>
<Datagrid>
<ReferenceField sortable={false} source="id" reference="items" linkType="show">
<TextField source="fieldB" />
</ReferenceField>
<TextField sortable={false} source="fieldC" />
<TextField sortable={false} source="fieldD" />
<DateField sortable={false} source="fieldE" />
{ (showFieldA === true) ? <TextField sortable={false} source="fieldA" /> : null }
<ShowButton />
<EditButton />
</Datagrid>
</List>
}
}
const ItemsFilter = (props) => (
<Filter {...props}>
<TextInput label="FilterSearch" source="q" />
<TextInput label="FilterA" source="fieldA" />
</Filter>
)
function mapStateToProps(state) {
return {
itemsFilters: state.admin.resources.items.list.params.filter
}
}
export default connect(mapStateToProps)(ItemList)
...
in App.js
<Resource name="items" list={ItemList} show={ItemShow} edit={ItemEdit} />
const MyList = (props) => {
const show = ... // if filter is set in URL
return (
<List {...props} filters={<MyFilter />}>
<Datagrid>
...
{show ? <TextField {...props} /> : null}
...
</Datagrid>
</List>
);
}