Search code examples
react-admin

Two different List components on a single page


So I'm trying to essentially have two lists on one screen, I have a wizard and in this step I'm linking entities, such as adding users to a profile

I used Use <List /> on React-Admin dashboard as a starting point, and then gave the entities different names, but still don't know how to do this. Basically the modal shouldn't be tied to the url, just a list of users that can be added to the profile, and then behind this modal is the list of users in that profile

initPropsLinkDeviceList = {
    basePath: "/profiles/create/link-devices",
    hasCreate: false,
    hasEdit: false,
    hasList: true,
    hasShow: false,
    history: {},
    location: { pathname: "/profiles/create/link-devices", search: "", hash: "", state: undefined },
    match: { path: "/profiles/create/link-devices", url: "/profiles/create/link-devices", isExact: true, params: {} },
    options: {},
    unlinked: "true",
    permissions: null,
    resource: "profile-users-unlinked",
    listactions: null,
    profileId: null,
}

In customRoutes:

    <Route exact path="/profiles/create/:id/:step" component={ProfileWizard} />,

In App: <Admin> <Resource name="profile-devices" /> <Resource name="profile-devices-unlinked" />

ProfileDevices.js

componentDidMount() {
    var initProps = {
        basePath: `/profiles/create/${this.props.match.params.id}/link-devices`,
        hasCreate: false,
        hasEdit: false,
        hasList: true,
        hasShow: false,
        history: {},
        location: { pathname: `/profiles/create/${this.props.match.params.id}/link-devices`, search: "", hash: "", state: undefined },
        match: { path: `/profiles/create/${this.props.match.params.id}/link-devices`, url: `/profiles/create/${this.props.match.params.id}/link-devices`, isExact: true, params: {} },
        options: {},
        unlinked: "true",
        permissions: null,
        resource: "profile-devices",
        profileId: this.props.match.params.id,
        listactions: <ProfileDevicesListActions profileId={this.props.match.params.id} />
    }
    this.setState({ 'initProps': initProps })
}
    render() {
    const {
        initProps
    } = this.state;

    if (!initProps) {
        return false;
    }


    return (
        <DevicesList {...initProps} {...this.props} />
    );
}

DevicesList:

            <List {...this.props}
            perPage={10}
            filters={<DeviceSearchFilter />}
            actions={this.props.listactions}
            bulkActionButtons={<DeviceBulkActions />} filterDefaultValues={
                {
                    id: 1,
                    unlinked: this.props.unlinked,
                    profileId: this.props.profileId
                }}>

Then I have the same initProps in LinkAction(the modal dialog)

In my dataprovider I've mapped both resources to the same api, so one just adds a filter to show all vs show specific to profileId

The two resources seem to be clashing even though they are different resources in redux, assuming this is due to the url routing, essentially I suppose I need the in the modal to not be tied to the url. Thanks

Just to add I realise I could probably achieve this by manually just calling dataProvider and handling them separately such as the demo dashboard, but wanted to get the 'magic' benefits of filter,paginiation etc.


Solution

  • The two resources seem to be clashing even though they are different resources in redux, assuming this is due to the url routing, essentially I suppose I need the in the modal to not be tied to the url.

    You're right about that. The List component is indeed tightly coupled to the url so having two of them inside the same page is not supported (see https://github.com/marmelab/react-admin/issues/2903).

    We don't have an answer for those cases yet and you'll have to implement your own List component for now.