Somebody
Somebody

Reputation: 347

Access Property of a Nested Record

I'm using React-Admin 3.5.0 with api-platform/admin 2.1.1.

I have a custom list for one of my resources.
The resource has a title and an author. The author has several properties, one of which is username.

Following the documentation, I tried to display the username of the author in my list like this:

export const MyList = (props) =>
    <List {...props}>
        <Datagrid>
            <TextField source="title" />
            <TextField source="author.username" />
        </Datagrid>
    </List>

This does not work. The field for author.username is empty.

I investigated a bit and found that the record only contains the ID of the author:

record:
    ...
    title: "abcde"
    author: "/users/1"

The response from the server however does contain the username property:

0: {
    ...,
    "title": "abcde",
    "author": {
        "@id": "/users/1",
        "username": "Test"
    }
},
...

Is there any nice way to make it work?

Upvotes: 3

Views: 1938

Answers (3)

Alan Poulain
Alan Poulain

Reputation: 301

I've created the PR to add support for arrays of embeddeds: https://github.com/api-platform/admin/pull/302.

It will be in the next version (a patch one).

Upvotes: 0

Lord_Fry
Lord_Fry

Reputation: 103

version 2.2 should support nested/embedded objects:

See https://api-platform.com/docs/admin/handling-relations/#display-a-field-of-an-embedded-relation

I tried it. Unfortunately, it didn't work for me...

import {
    fetchHydra
    HydraAdmin,
    hydraDataProvider as baseHydraDataProvider,
} from "@api-platform/admin";

const dataProvider = baseHydraDataProvider(
    entrypoint,
    fetchHydra,
    apiDocumentationParser,
    true // use embedded!
);

export default () => (
    <HydraAdmin
        dataProvider={dataProvider} authProvider={authProvider} entrypoint={entrypoint} i18nProvider={i18nProvider}>
        <ResourceGuesser name={"users"} list={UserList} icon={UserIcon}/>
         ....
    </HydraAdmin>

record input v.s. transmitted input

How to debug

Log the converted record data into your console (this causes some error, but at least you see what really happens).

const TagsField = ({record, ...props}) => (
    <ArrayField source="images">
        {console.log("Record:")}
        {console.log(record)}
        <TextField source="image"/>
    </ArrayField>
)
... 
export const HouseList = (props) => (
<ListGuesser title="houses" {...props}>
    ....
    <NumberField source="price" label="Price (€)"/>
    <TagsField label="Images" source="images" sortable={false}>
    </TagsField>
    ....

Has someone an idea, what I did wrong over here?

Even more details

https://github.com/api-platform/admin/pull/299

Upvotes: 1

gstvg
gstvg

Reputation: 927

Found this on api-platform admin source code:

Replace embedded objects by their IRIs, and store the object itself in the cache to reuse without issuing new HTTP requests.

And right below:

document[key] = document[key]['@id'];

https://github.com/api-platform/admin/blob/ba0630083f28eaa8806bc1da4613677924604a52/src/hydra/dataProvider.js#L75

This behavior came from this pull request:

https://github.com/api-platform/admin/pull/96

To display author fields, you will need to use a ReferenceField for each one of them:

export const MyList = (props) =>
    <List {...props}>
        <Datagrid>
            <TextField source="title" />
            <ReferenceField source="author" reference="users">
                <TextField source="username"/>
            </ReferenceField>

            <ReferenceField source="author" reference="users" link={false}>
                <TextField source="email"/>
            </ReferenceField>
        </Datagrid>
    </List>

Doing it will make the author fields link to the author page. You can disable this passing link={false} on the ReferenceField, like on the second author field above

React admin will pack all those author reference requests into a single one, so even if api-platform data provider woun't do it's cache promise, you will endup with only one http request.

Note: You must add a <Resource> for the reference resource - react-admin needs it to fetch the reference data. You can omit the list prop in this reference if you want to hide it in the sidebar menu.

Upvotes: 2

Related Questions