import React , { FC , cloneElement , Children , ReactElement } from 'react' ; import PropTypes from 'prop-types' ; import { FilterPayload , SortPayload , useReferenceManyFieldController , ListContextProvider , ListControllerProps , ResourceContextProvider , useRecordContext , ReduxState , } from 'ra-core' ; import { useSelector } from 'react-redux' ; import { PublicFieldProps , fieldPropTypes , InjectedFieldProps } from './types' ; import sanitizeFieldRestProps from './sanitizeFieldRestProps' ; example example example example example export const ReferenceManyField = props => { const { basePath , children , filter , page = 1 , perPage , reference , resource , sort , source , target , } = props ; const record = useRecordContext ( props ) ; if ( React . Children . count ( children ) !== 1 ) { throw new Error ( '<ReferenceManyField> only accepts a single child (like <Datagrid>)' ) ; } const isReferenceDeclared = useSelector < ReduxState , boolean > ( state => typeof state . admin . resources [ props . reference ] !== 'undefined' ) ; if ( ! isReferenceDeclared ) { throw new Error ( `You must declare a <Resource name="${ props . reference }"> in order to use a <ReferenceManyField reference="${ props . reference }">` ) ; } const controllerProps = useReferenceManyFieldController ( { basePath , filter , page , perPage , record , reference , resource , sort , source , target , } ) ; return ( < ResourceContextProvider value = { reference } > < ListContextProvider value = { controllerProps } > < ReferenceManyFieldView { ... props } { ... controllerProps } /> < /ListContextProvider> < /ResourceContextProvider>); } ; export interface ReferenceManyFieldProps extends PublicFieldProps , InjectedFieldProps { children : ReactElement ; filter ? : FilterPayload ; page ? : number ; pagination ? : ReactElement ; perPage ? : number ; reference : string ; sort ? : SortPayload ; target : string ; } ReferenceManyField . propTypes = { addLabel : PropTypes . bool , basePath : PropTypes . string , children : PropTypes . element . isRequired , className : PropTypes . string , filter : PropTypes . object , label : PropTypes . string , perPage : PropTypes . number , record : PropTypes . any , reference : PropTypes . string . isRequired , resource : PropTypes . string , sortBy : PropTypes . string , sortByOrder : fieldPropTypes . sortByOrder , source : PropTypes . string . isRequired , sort : PropTypes . exact ( { field : PropTypes . string , order : PropTypes . string , } ) , target : PropTypes . string . isRequired , } ; ReferenceManyField . defaultProps = { filter : { } , perPage : 25 , sort : { field : 'id' , order : 'DESC' } , source : 'id' , addLabel : true , } ; export const ReferenceManyFieldView = props => { const { basePath , children , pagination , reference , ... rest } = props ; return ( < > { cloneElement ( Children . only ( children ) , { ... sanitizeFieldRestProps ( rest ) , basePath , resource : reference , } ) } { pagination && props . total !== undefined && cloneElement ( pagination ) } < />); } ; export interface ReferenceManyFieldViewProps extends Omit < ReferenceManyFieldProps , 'basePath' | 'resource' | 'page' | 'perPage' > , ListControllerProps { children : ReactElement ; } ReferenceManyFieldView . propTypes = { basePath : PropTypes . string . isRequired , children : PropTypes . element , className : PropTypes . string , currentSort : PropTypes . exact ( { field : PropTypes . string , order : PropTypes . string , } ) , data : PropTypes . any , ids : PropTypes . array , loaded : PropTypes . bool , pagination : PropTypes . element , reference : PropTypes . string , setSort : PropTypes . func , } ; export default ReferenceManyField ;