I am trying to hide a set of fields based on the value of another field but the following will not display the conditional fields ever:
export const ServiceShow = (props) => (
<ShowController {...props}>
{controllerProps =>
<ShowView component="div" {...props} {...controllerProps}>
<TabbedShowLayout>
<Tab label="General">
{controllerProps.record && controllerProps.record.maintenance &&
controllerProps.record.maintenance.active &&
<>
<Alert severity="warning">Maintenance period active</Alert>
<DateField label="Maintenance Start" src="maintenance.start" />
<DateField label="Maintenance End" srvc="maintenance.end" />
<TextField label="Maintenance Message" source="maintenance.msg" />
</>
}
</Tab>
</TabbedShowLayout>
</ShowView>
}
</ShowController>
);
The <Alert> is displayed just fine, but the Field components are not. I'm very new to React so probably a simple thing.
Note:If I put a single <TextField> as the conditional output then it will work but anything inside a React.Fragment or <div> for example, it doesn't work.
The reason why Alert shows up and Fields not is because Fields require addtional props passed by react-admin direct parent, in that case, the Tab. <> should pass such props too, but looks like it's not. And thats why a single <TextField> as child renders correctly
You can create a component that pass the props downstream to childs.
export const ServiceShow = (props) => (
<ShowController {...props}>
{controllerProps =>
<ShowView component="div" {...props} {...controllerProps}>
<TabbedShowLayout>
<Tab label="General">
<Maintenance/>
</Tab>
</TabbedShowLayout>
</ShowView>
}
</ShowController>
);
const Maintenance = props => (
{props.record && props.record.maintenance && props.record.maintenance.active &&
<>
<Alert {...props} severity="warning">Maintenance period active</Alert>
<DateField {...props} label="Maintenance Start" src="maintenance.start" />
<DateField {...props} label="Maintenance End" srvc="maintenance.end" />
<TextField {...props}label="Maintenance Message" source="maintenance.msg" />
</>
}
)
Related
I am trying to filter a list in react-admin.
Basically, I have a list of classes, that I want to filter by teacherId. However, the teacherId has to be fetched asynchronously.
The code looks like this:
const activitiesFilters = [
<TextInput key="search" source="q" label="Search an Activity" alwaysOn />,
]
export const ActivityList = (props) => {
const teacher = useCurrentTeacherProfile() // This is the asynchronous call
return (
<List
filters={activitiesFilters}
filter={{ authorId: teacher?.id }} // Here I am using the teacher ID to filter my list
{...props}
exporter={false}
>
<Datagrid rowClick="edit">
<TextField source="id" />
<TextField source="title" />
<TextField source="location" />
<DateField source="dateTime" />
</Datagrid>
</List>
)
}
The above code gives me this error:
Error: ActivityList suspended while rendering, but no fallback UI was specified. Add a <Suspense fallback=...> component higher in the tree to provide a loading indicator or placeholder to display.
I tried adding a <Suspense /> component above the <List /> but it doesn't work.
And if I add the <Suspense /> component at the root, above the <Admin /> one, it breaks the navigation.
Is there a way I can filter my list with a parameter that is fetched asynchronously?
Thanks!
I wonder if the error does not come from the "?." typescript operator in "teacher?.id" that resolves to undefined in JS before your async call resolves.
So I'd resolve the code as follow:
import { Loading } from 'react-admin';
const activitiesFilters = [
<TextInput key="search" source="q" label="Search an Activity" alwaysOn />,
]
export const ActivityList = (props) => {
const teacher = useCurrentTeacherProfile() // This is the asynchronous call
if (!teacher) return <Loading/>
return (
<List
filters={activitiesFilters}
filter={{ authorId: teacher?.id }} // Here I am using the teacher ID to filter my list
{...props}
exporter={false}
>
<Datagrid rowClick="edit">
<TextField source="id" />
<TextField source="title" />
<TextField source="location" />
<DateField source="dateTime" />
</Datagrid>
</List>
)
}
I cant work out how to pass props to Box component override.
I need to pass position="end"" as required by InputAdornment but cant find how in the docs.
Full component is
<Select
value={value}
onChange={handleChange}
input={
<OutlinedInput
endAdornment={
photoRequired && (
<Box component={InputAdornment} position="end" pr={3}>
{required && <Gallery />}
<Gallery />
</Box>
)
}
/>
}
>
{choices.map((choice, i) => (
<MenuItem key={i} value={i + 1}>
{choice}
</MenuItem>
))}
</Select>
I am getting error trying to pass in the way above as its not expected on Box.
Warning: Failed prop type: The prop `position` is marked as required in `ForwardRef(InputAdornment)`, but its value is `undefined`.```
Try creating your own InputAdornment component that uses the position, such as:
const EndInputAdornment = () => {
return <InputAdornment position="end"/>
};
Then you can use that component to the Box:
<Box component={EndInputAdornment} pr={3}>
...
or if you don't want to create a separate component:
<Box component={<InputAdornment position="end"/>} pr={3}>
should work
I am building a custom show page for an individual customer. Within this page I need a button that allows me to edit their points value they have. I am wanting to use the aside component that is built in react-admin but I can't seem to get it to work correctly.
I have followed the documentation to add the code for the aside component and I placed my button component within it. However it's not rendering to the page at all. I am receiving a TypeError. 'TypeError: Cannot read roperty "search" of undefined.'
const Aside = (...props) => {
const { customer_id: customer_id_string } = parse(props.location.search);
const customer_id = customer_id_string ? parseInt(customer_id_string, 10) : '';
return (
<div style={{ width: 200, margin: '1em'}}>
<Button
defaultValue={{ customer_id }}
redirect="show"
component={Link}
to={{
pathname: '/points/{{point-id}}/create',
}}
label="Add Points"
>
<Reward>Add Points</Reward>
</Button>
)
</div>
)
};
const CustomerShow = ({ classes, record, ...props }) => (
<Show aside={<Aside />} {...props}>
<TabbedShowLayout>
<Tab label="Customer Basics">
<TextField source="firstName" /><TextField source="lastName" />
<TextField source="email" />
<BooleanField source="active" />
</Tab>
<Tab label="The Rest">
<NumberField label="Points" source="points" />
<NumberField source="usedPoints" />
<NumberField source="expiredPoints" />
<NumberField source="lockedPoints" />
<BooleanField source="agreement1" />
<BooleanField source="agreement2" />
</Tab>
<Tab label="Transactions" resource="transactions" >
<ReferenceManyField
addLabel={false}
reference="transactions"
target="customerId"
pagination={<Pagination />}
perPage={10}
sort={{ field: 'createdAt', order: 'DESC' }}
><Datagrid rowClick="show" >
<DateField source="createdAt"/>
<TextField source="documentNumber"/>
<TextField source="documentType"/>
<NumberField source="grossValue"/>
<NumberField source="pointsEarned"/>
<NumberField source="pointsUsed"/>
</Datagrid>
</ReferenceManyField>
</Tab>
<Tab label="Points" resource="Points" >
<ReferenceManyField
addLabel={false}
reference="points"
target="customerId"
pagination={<Pagination />}
perPage={10}
sort={{ field: 'createdAt', order: 'DESC' }}
><Datagrid rowClick="show" >
<NumberField source="valueLocked" />
<NumberField source="valueUsed" />
<NumberField source="valueRemain" />
<NumberField source="valueExpired" />
<NumberField source="valueEarned" />
</Datagrid>
</ReferenceManyField>
</Tab>
</TabbedShowLayout>
</Show>
);
The expected results are a button on the right side of the page displaying the words "Add Points". The actual results are either a TypeError or the page renders but no button.
I figured out what I was doing wrong. I didn't have one of my sources filled out correctly. It was referencing the wrong source.
Using React-admin, I am using the ShowController component, which gives me more freedom to customize the ShowView. However, I would like to keep seeing the labels in the TextFields, but, they are gone.
This piece of code shows how I am using the ShowController and, it works partially: only show the record values, not the labels (I also tried without the prop "label", it doesn't work neither).
const OrderShow = props => {
return (<ShowController {...props}>
{controllerProps => {
return (
<Grid container spacing={8}>
<Grid item xs={3}>
<TextField label="ID" source="id" {...controllerProps} />
...
What is missing to show the labels as in the ShowView standard component?
TextFields' labels are usually filled by their source property.
If you want to use <ShowController> component with custom layout, I suggest you to create another custom component and use it inside of <Show>, <ShowView> or <SimpleShowLayout>.
I wrapped the fields with SimpleForm component to be able to show their labels and hide the Toolbar with custom CardActions.
Example:
const FormToolbar = () => (
<CardActions style={{display: 'none'}}>
</CardActions>
);
const FormDiv = ({controllerProps, ...props}) => (
<Grid container spacing={24}>
<Grid item xs={12}>
<SimpleForm toolbar={<FormToolbar/>}>
<TextField {...props} record={controllerProps.record} source="name"/>
</SimpleForm>
</Grid>
</Grid>
);
const OrderShow = props => (
<ShowController {...props} title="Order">
{controllerProps =>
<Show actions={<ShowActions pageType="show" />} {...props} {...controllerProps}>
<SimpleShowLayout>
<FormDiv controllerProps={controllerProps} />
</SimpleShowLayout>
</Show>
}
</ShowController>
);
export default OrderShow;
I've got a translation issue on admin-on-rest. My tabs have labels when FormTab are directly inside the Edit component.
The tab title is empty for the third one only. I've got an error (MyCustomFormTab) :
Warning: Missing translation for key: "undefined"
const EditComponent = props => (
<Edit {...props}>
<TabbedForm>
<FormTab label="tab Title" />
<FormTab label="Other Tab Title" />
<MyCustomFormTab />
</TabbedForm>
</Edit>
)
const MyCustomFormtab = props => (
<FormTab label="My Custom tab Title" />
)
Am I doing something wrong ?
FormTab components must be direct children of the TabbedForm component.