React-admin: Provided selectedIds to Datagrid do not the pre check the checkboxes

Created on 6 Jul 2018  路  19Comments  路  Source: marmelab/react-admin

What you were expecting:
I expected an array of selectedIds provided as a prop to Datagrid to cause the checkboxes to be initially checked at the records with an id included in that list of selectedIds.

What happened instead:
The checkboxes are not checked.

Steps to reproduce:
Provide a selectedIds prop with an array of id's to a Datagrid.

Related code:
https://codesandbox.io/s/xr8z4jvr5q

<Datagrid selectedIds={[13, 12]}>
  ....
</Datagrid>

image

Environment

  • React-admin version: 2.0.4
  • Last version that did not exhibit the issue (if applicable): n/a
  • React version: 16.3.1
  • Browser: any
  • Stack trace (in case of a JS error): n/a

Most helpful comment

Until now I have managed to cross rivers without much knowledge of sagas and generator functions. When high tides arrive and I need to cross, I'll make sure to acquire it. Thanks for your help today! It was really valuable to me.

All 19 comments

PS: What I much rather would do is to provide a function to Datagrid that is called for each record. That function would return true or false and would determine whether the checkbox for that record is initially checked. This comment is not part of the bug report though.

_Update. The function is passed the record, so it can decide based on the record values whether it should return or false._

What's your use-case ?

If you're using the Datagrid inside a List component then it's normal as your selectedIds will be overridden by the List component which passes selectedIds to the Datagrid

With all the checked records I do a bulk UPDATE_MANY with some status.

However, if some records already have that status before presenting the list, that list has to show those records already checked.

Providing selectedIds={[10, 11]} to List also doesn't pre-check the records. I updated the linked sandbox.

Interesting use-case. Indeed, the selectedIds is managed entirely through the redux state so you won't be able to override it this way. Give me some time to verify how you could that.

But again, I would much rather provide a function to Datagrid that is executed for each record and decides (based on the data in the record) whether the checkbox is checked initially. See my comment above.

But the array is fine too :)

Turns out it can be achieved with a custom saga. For example, checking all commentable posts by default:

import { put, takeEvery } from "redux-saga/effects";
import { CRUD_GET_LIST_SUCCESS, setListSelectedIds } from "react-admin";

function* selectedIdsSaga(action) {
  if (action.meta.resource === "posts") {
    const selectedIds = action.payload.data
      .filter(item => item.commentable)
      .map(item => item.id);

    yield put(setListSelectedIds("posts", selectedIds));
  }
}

export default function*() {
  yield takeEvery(CRUD_GET_LIST_SUCCESS, selectedIdsSaga);
}

See it in action in this codesandbox (forked from yours)

Great, it helps, but not entirely. In my exact use-case, the condition that defines if the record should be selected is dynamic and based on a parent record. So, one can not only look at the record itself (as you did in the custom saga with item.commentable. What you did though is exactly targeted at how I outlined my use-case. I shouldn't have simplified. That I realize now.

This better reflects my use-case. Assume:

  • The parent Companies have ids: 1 and 2
  • The child Employees have ids: 1, 2, 3, 4, 5, 6, ...
  • All employees are linked to Company 1.

I present a dialog with a List of all 6 Employees in the context of Company 1. All employee records are selected.
I present a dialog with a lLst of all 6 Employees in the context of Company 2. All employee records are not selected.

In the custom saga, there's no reference to that parent record (Company). As it stands, there's no way to determine selected or not.

I have the record id of the parent in the url. So, the saga would be able to retrieve that. I don't know how though.

This is my url: /companies/:id/employees

That's a custom route that opens a dialog with a list of all employees. Not just the employees of the company, but really all employees. It allows you to assign the employees to the company with the id in the url.

I've solved it by providing filter={{__ignore: {companyId: 1}}} to the List of Employees in my dialog.

In my custom rest client, I'm already skipping all filters that start with __ in my REST request. But the complete filter is visible in action.requestPayload in the saga. I'm using that now to decide whether or not to check the employee checkbox.

So my saga looks like this:

import { put, takeEvery } from "redux-saga/effects";
import { CRUD_GET_LIST_SUCCESS, setListSelectedIds } from "react-admin";

function* selectedIdsSaga(action) {
  if (action.meta.resource === "employees") {
    const { requestPayload } = action;
    const selectedIds = action.payload.data
      .filter(item => item.companyId === requestPayload.filter.__companyId)
      .map(item => item.id);

    yield put(setListSelectedIds("employees", selectedIds));
  }
}

export default function*() {
  yield takeEvery(CRUD_GET_LIST_SUCCESS, selectedIdsSaga);
}

I have the record id of the parent in the url. So, the saga would be able to retrieve that. I don't know how though.

Get the location from the router state.

Until now I have managed to cross rivers without much knowledge of sagas and generator functions. When high tides arrive and I need to cross, I'll make sure to acquire it. Thanks for your help today! It was really valuable to me.

Thanks for your feedbacks! Please continue to challenge this library with this kind of use cases :)

@christiaanwesterbeek I am also trying to achieve a similar task, whereby I can bulk add records from a 'activities' resource via a List in a Dialog, from within the edit view of a record from another 'collection' resource. I am also trying to pre-check the list boxes in the grid, but have had no success with the __ignore method in the filter. Can you please shed some light on how to implement this? Do I import __ignore from somewhere? or are there keywords that work with the filter? Thanks!

@lafeer The __xxx filters is a construct the I made up myself. It's no standard of react-admin or something you can import to make that work.

You need to make changes to your ra-xxx-client to make it actually ignore those filters that start with __.

Thanks for your response @christiaanwesterbeek.

As I'm new to react and react-admin I'm not quite sure how to go about that, would you be able to share an example of how i can implement the __xxx filters? I am currently only using fake data with ra-data-json-server

Was this page helpful?
0 / 5 - 0 ratings

Related issues

9747749366 picture 9747749366  路  3Comments

ericwb picture ericwb  路  3Comments

fzaninotto picture fzaninotto  路  3Comments

nicgirault picture nicgirault  路  3Comments

aserrallerios picture aserrallerios  路  3Comments