-
-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8492 from marmelab/count-components
Add Count and ReferenceManyCount components
- Loading branch information
Showing
19 changed files
with
955 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
--- | ||
layout: default | ||
title: "The Count Component" | ||
--- | ||
|
||
# `<Count>` | ||
|
||
When you need to render the number of records of a given resource, use the `<Count>` component. It calls `dataProvider.getList()` with the `pagination` parameter set to retrieve no data - only the total number of records. | ||
|
||
![Count](./img/count.webp) | ||
|
||
## Usage | ||
|
||
The most basic usage is to count the number of records in the current resource. For example, to count the number of posts: | ||
|
||
```jsx | ||
import { Count } from 'react-admin'; | ||
|
||
const PostCount = () => <Count />; | ||
``` | ||
|
||
`<Count>` is usually used inside custom Menus, to display the number of records in each category. This takes advantage of [the `filter` prop](#filter) to count the number of records matching a given filter. For example, to build a menu for the various statuses of tickets in a Helpdesk: | ||
|
||
{% raw %} | ||
```jsx | ||
import { Count, useStore } from 'react-admin'; | ||
import { MenuList, MenuItem, ListItemText } from '@mui/material'; | ||
import { isEqual } from 'lodash'; | ||
|
||
const TicketListAside = () => { | ||
const [statusFilter, setStatusFilter] = useStore("statusMenu", { status: 'open' }); | ||
return ( | ||
<MenuList> | ||
<MenuItem | ||
onClick={() => setStatusFilter({ status: 'open' })} | ||
selected={isEqual(statusFilter, { status: 'open' })} | ||
> | ||
<ListItemText>Open</ListItemText> | ||
<Count filter={{ status: 'open' }} /> | ||
</MenuItem> | ||
<MenuItem | ||
onClick={() => setStatusFilter({ status: 'pending' })} | ||
selected={isEqual(statusFilter, { status: 'pending' })} | ||
> | ||
<ListItemText>Pending</ListItemText> | ||
<Count filter={{ status: 'pending' }} /> | ||
</MenuItem> | ||
<MenuItem | ||
onClick={() => setStatusFilter({ status: 'closed' })} | ||
selected={isEqual(statusFilter, { status: 'closed' })} | ||
> | ||
<ListItemText>Closed</ListItemText> | ||
<Count filter={{ status: 'closed' }} /> | ||
</MenuItem> | ||
<MenuItem | ||
onClick={() => setStatusFilter({})} | ||
selected={isEqual(statusFilter, {})} | ||
> | ||
<ListItemText>All</ListItemText> | ||
<Count filter={{}} /> | ||
</MenuItem> | ||
</MenuList> | ||
); | ||
}; | ||
``` | ||
{% endraw %} | ||
|
||
|
||
## Props | ||
|
||
| Prop | Required | Type | Default | Description | | ||
| ---------- | -------- | ------ | ------- | ----------------------------------------------------------------------- | | ||
| `filter` | Optional | Object | - | Filter to apply to the query. | | ||
| `link` | Optional | bool | `false` | If true, the count is wrapped in a `<Link>` to the list view. | | ||
| `resource` | Optional | string | - | Resource to count. Default to the current `ResourceContext` | | ||
| `timeout` | Optional | number | 1000 | Number of milliseconds to wait before displaying the loading indicator. | | ||
|
||
Additional props are passed to [the underlying MUI `<Typography>` element](https://mui.com/material-ui/api/typography/). | ||
|
||
## `filter` | ||
|
||
If you want to count the number of records matching a given filter, pass it as the `filter` prop. For example, to count the number of posts already published: | ||
|
||
{% raw %} | ||
```jsx | ||
<Count resource="posts" filter={{ is_published: true }} />; | ||
``` | ||
{% endraw %} | ||
|
||
## `link` | ||
|
||
If you want to wrap the count in a `<Link>` to the list view, pass `true` to the `link` prop. | ||
```jsx | ||
<Count link /> | ||
``` | ||
|
||
When used in conjunction to the `filter` prop, the link will point to the list view with the filter applied. | ||
|
||
{% raw %} | ||
```jsx | ||
<Count link filter={{ is_published: true }} link /> | ||
``` | ||
{% endraw %} | ||
|
||
## `resource` | ||
|
||
By default, the `<Count>` component uses the current `ResourceContext`, so you don't need to pass the `resource` prop to count the number of records in the current Resource. | ||
|
||
```jsx | ||
<Count /> | ||
``` | ||
|
||
If you want to count a different resource, pass it as the `resource` prop. | ||
|
||
```jsx | ||
<Count resource="comments" /> | ||
``` | ||
|
||
## `timeout` | ||
|
||
The `<Count>` component displays a loading indicator after 1 second. This is useful to avoid displaying a loading indicator when the count is retrieved in a few milliseconds. You can change this delay by passing a `timeout` prop. | ||
|
||
```jsx | ||
<Count timeout={500} /> | ||
``` | ||
|
||
## Counting Related Records | ||
|
||
If you need to count the number of records related to the current one via a one-to-many relationship, use [the `<ReferenceManyCount>` component](./ReferenceManyCount.md) instead. | ||
|
||
![ReferenceManyCount](./img/ReferenceManyCount.webp) | ||
|
||
```jsx | ||
import { | ||
ChipField | ||
Datagrid, | ||
DateField, | ||
List, | ||
NumberField, | ||
ReferenceArrayField, | ||
ReferenceManyCount, | ||
SingleFieldList, | ||
TextField, | ||
} from 'react-admin'; | ||
|
||
export const PostList = () => ( | ||
<List> | ||
<Datagrid> | ||
<TextField source="id" /> | ||
<TextField source="title" /> | ||
<DateField source="published_at" sortByOrder="DESC" /> | ||
<ReferenceManyCount | ||
label="Comments" | ||
reference="comments" | ||
target="post_id" | ||
/> | ||
<NumberField source="views" sortByOrder="DESC" /> | ||
<ReferenceArrayField | ||
label="Tags" | ||
reference="tags" | ||
source="tags" | ||
> | ||
<SingleFieldList> | ||
<ChipField source="name.en" size="small" /> | ||
</SingleFieldList> | ||
</ReferenceArrayField> | ||
</Datagrid> | ||
</List> | ||
) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
--- | ||
layout: default | ||
title: "The ReferenceManyCount Component" | ||
--- | ||
|
||
# `<ReferenceManyCount>` | ||
|
||
When you need to render the number of records related to another record via a one-to-many relationship (e.g. the number of comments related to a post), use the `<ReferenceManyCount>` component. It calls `dataProvider.getManyReference()` with the `pagination` parameter set to retrieve no data - only the total number of records. | ||
|
||
![ReferenceManyCount](./img/reference_many_count.webp) | ||
|
||
## Usage | ||
|
||
Use `<ReferenceManyCount>` as a regular Field in a `<Datagrid>` or `<SimpleShowLayout>` - or anywhere inside a [`RecordContext`](./useRecordContext.md). You must set the `reference` and `target` props to match the relationship: | ||
|
||
- `reference` is the name of the related resource to fetch (e.g. `comments`) | ||
- `target` is the name of the field in the related resource that points to the current resource (e.g. `post_id`) | ||
|
||
```jsx | ||
import { | ||
ChipField | ||
Datagrid, | ||
DateField, | ||
List, | ||
NumberField, | ||
ReferenceArrayField, | ||
ReferenceManyCount, | ||
SingleFieldList, | ||
TextField, | ||
} from 'react-admin'; | ||
|
||
export const PostList = () => ( | ||
<List> | ||
<Datagrid> | ||
<TextField source="id" /> | ||
<TextField source="title" /> | ||
<DateField source="published_at" sortByOrder="DESC" /> | ||
<ReferenceManyCount | ||
label="Nb comments" | ||
reference="comments" | ||
target="post_id" | ||
link | ||
/> | ||
<NumberField source="views" sortByOrder="DESC" /> | ||
<ReferenceArrayField | ||
label="Tags" | ||
reference="tags" | ||
source="tags" | ||
> | ||
<SingleFieldList> | ||
<ChipField source="name.en" size="small" /> | ||
</SingleFieldList> | ||
</ReferenceArrayField> | ||
</Datagrid> | ||
</List> | ||
) | ||
``` | ||
|
||
**Tip**: If you need to count all the records of a given resource, use [the `<Count>` component](./Count.md) instead. | ||
|
||
## Props | ||
|
||
| Prop | Required | Type | Default | Description | | ||
| ----------- | -------- | ------ | ------- | ------------------------------------------------------------------------- | | ||
| `reference` | Required | string | - | Name of the related resource to fetch (e.g. `comments`) | | ||
| `target` | Required | string | - | Name of the field in the related resource that points to the current one. | | ||
| `filter` | Optional | Object | - | Filter to apply to the query. | | ||
| `link` | Optional | bool | `false` | If true, the count is wrapped in a `<Link>` to the filtered list view. | | ||
| `resource` | Optional | string | - | Resource to count. Default to the current `ResourceContext` | | ||
| `timeout` | Optional | number | 1000 | Number of milliseconds to wait before displaying the loading indicator. | | ||
|
||
`<ReferenceManyCount>` also accepts the [common field props](./Fields.md#common-field-props). | ||
|
||
Additional props are passed to [the underlying MUI `<Typography>` element](https://mui.com/material-ui/api/typography/). | ||
|
||
## `filter` | ||
|
||
If you want to count the number of records matching a given filter, pass it as the `filter` prop. For example, to count the number of comments already published: | ||
|
||
{% raw %} | ||
```jsx | ||
<ReferenceManyCount | ||
label="Comments" | ||
reference="comments" | ||
target="post_id" | ||
filter={{ is_published: true }} | ||
/> | ||
``` | ||
{% endraw %} | ||
|
||
## `link` | ||
|
||
If you want to wrap the count in a `<Link>` to the list view filtered for the current record, pass `true` to the `link` prop. | ||
|
||
```jsx | ||
<ReferenceManyCount | ||
label="Comments" | ||
reference="comments" | ||
target="post_id" | ||
link | ||
/> | ||
``` | ||
|
||
When used in conjunction to the `filter` prop, the link will point to the list view with the filter applied. | ||
|
||
{% raw %} | ||
```jsx | ||
<ReferenceManyCount | ||
label="Comments" | ||
reference="comments" | ||
target="post_id" | ||
link | ||
filter={{ is_published: true }} | ||
/> | ||
``` | ||
{% endraw %} | ||
|
||
## `reference` | ||
|
||
The `reference` prop is required and must be the name of the related resource to fetch. For instance, to fetch the number of comments related to the current post: | ||
|
||
```jsx | ||
<ReferenceManyCount | ||
label="Comments" | ||
reference="comments" | ||
target="post_id" | ||
/> | ||
``` | ||
|
||
## `resource` | ||
|
||
By default, the `<ReferenceManyCount>` component uses the current `ResourceContext`, so you don't need to pass the `resource` prop to count the number of records in the current Resource. If you want to count a different resource, pass it as the `resource` prop. | ||
|
||
```jsx | ||
<ReferenceManyCount | ||
label="Comments" | ||
reference="comments" | ||
target="post_id" | ||
resource="posts" | ||
/> | ||
``` | ||
|
||
## `target` | ||
|
||
The `target` prop is required and must be the name of the field in the related resource that points to the current one. For instance, when fetching the number of comments related to the current post, if a comment relates to a post via a `post_id` foreign key, you must set the `target` prop to `post_id`: | ||
|
||
```jsx | ||
<ReferenceManyCount | ||
label="Comments" | ||
reference="comments" | ||
target="post_id" | ||
/> | ||
``` | ||
|
||
## `timeout` | ||
|
||
The `<ReferenceManyCount>` component displays a loading indicator after 1 second. This is useful to avoid displaying a loading indicator when the count is retrieved in a few milliseconds. You can change this delay by passing a `timeout` prop. | ||
|
||
```jsx | ||
<ReferenceManyCount | ||
label="Comments" | ||
reference="comments" | ||
target="post_id" | ||
timeout={500} | ||
/> | ||
``` |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.