Hi, I am using 'process' and onDataStateChange to have the grid handle filter, sort and pagination. I have implemented a SelectAll functionality on top of this code. When I filter in data and then click on header Select, it selects 3 items but shows that all data is selected. Any idea of how to fix this?
https://stackblitz.com/edit/react-9odprj?file=app/Reusegrid.jsx
Also, how do I style checkboxes in the grid? I need to add classes to the input as well as the label tag in the checkbox. Please advice.
21 Answers, 1 is accepted
Sorry, indeed I saw the last one saying that it worked and tough that it is all resolved.
Is it possible, to only reply with the remaining issue, so I can provide more to the point answer to it.
Thank you in advance.
Regards,
Stefan
Progress Telerik
Sorry Stefan, my bad.
The main issue is that after filtering, I click on the SelectAll checkbox, instead of returning the selected rows results, it returns me the whole dataset.
https://stackblitz.com/edit/react-9odprj?file=app/Reusegrid.jsx
P.S: I also tried modifying the checkboxes to be more native than the Kendo UI ones and I was able to get it working for the rows but not for the header (SelectAll).
https://stackblitz.com/edit/react-9odprj-j7rxks?file=app/Reusegrid.jsx
Please advice.
Thank you for the clarification.
The issue occurs because on the header selecttion event, the entire data is set to the "setSelectedRows" method. If only the filtered data has to be set, pass the processed data:
const headerSelectionChange = event => {
const { checked } = event.syntheticEvent.target;
setData(
map(data, item => {
item.selected = checked;
return
item;
})
);
if
(checked) {
setSelectedRows(process(data, { sort, filter, skip, take }).data);
}
else
{
setSelectedRows([]);
}
};
For the second issue, in the provided example the Select all is working as well. Did I missed something?
https://www.screencast.com/t/rK8UMcPX39o
Regards,
Stefan
Progress Telerik
Hi Stefan, that works. One small bug is that I filter down the data and click selectAll, so the current one's in the page are selected. I start clearing out the filter one character by character, it looks like the whole dataset is selected in terms of checkbox. Can you please help me out on that issue? And regarding the custom checkbox, I made it to work. Is that the best way to achieve it or is there an alternative to get things good?
I also edited the headerSelection method like this.
const headerSelectionChange = event => {
const checked = !isEmpty(event.syntheticEvent)
? event.syntheticEvent.target.checked
: selectAllValue.selectionValue;
const processedData = process(data, { sort, filter, skip, take }).data
setData(
map(data, item => {
item.selected = processedData.includes(item);
return
item;
})
);
if
(checked) {
setSelectedRows(processedData);
}
else
{
selectAllValue.selectionValue = !checked;
setSelectedRows([]);
}
};
Without updating the data, selectAll works fine. Now with this new code, I am unable to select the header checkbox.
Hi Stefan, that works. One small bug is that I filter down the data and click selectAll, so the current one's in the page are selected. I start clearing out the filter one character by character, it looks like the whole dataset is selected in terms of checkbox. Can you please help me out on that issue? And regarding the custom checkbox, I made it to work. Is that the best way to achieve it or is there an alternative to get things good?
I also edited the headerSelection method like this.
const headerSelectionChange = event => {
const checked = !isEmpty(event.syntheticEvent)
? event.syntheticEvent.target.checked
: selectAllValue.selectionValue;
const processedData = process(data, { sort, filter, skip, take }).data
setData(
map(data, item => {
item.selected = processedData.includes(item);
return
item;
})
);
if
(checked) {
setSelectedRows(processedData);
}
else
{
selectAllValue.selectionValue = !checked;
setSelectedRows([]);
}
};
Without updating the data, selectAll works fine. Now with this new code, I am unable to select the header checkbox.
[/quote]
This is the new link: https://stackblitz.com/edit/react-9odprj-j7rxks?file=app/Reusegrid.jsx
I type in 'Ali' in the product name field, count becomes 3. I select All, all checkboxes including the header should be clicked. I delete the filter character by character, selectAll should be unchecked but the previously selected items should be checked.
@Stefan, I fixed as most as defects as I can here.
https://stackblitz.com/edit/react-9odprj-ap6so8
Could you please let me know if this is the best way to achieve selection with filtering and anything I might miss?
I`m glad that most of the issues are resolved.
After looking at the last link it seems that everything works are expected.
The selectAll selects all filtered items, and when the filter is cleared, only they shows as filtered:
https://www.screencast.com/t/e5qzM9ims
In general, there is no best approach as everything will depend on the application requirements. Sometimes, if the data is filtered and the all is clicked all data has to be selected even if the filter is removed and sometimes not. This is why we give full control to the developer over the selected items, to decide which is the best behavior based on the application business logic.
Regards,
Stefan
Progress Telerik
@Stefan Just one small issue. When I send in two or more values as preselected values from the parent, I try to uncheck atleast one of them, both of them get unchecked. Could you please help me out on this? It works fine if there is only one preselected value and to be unchecked. The link here shows this.
https://stackblitz.com/edit/react-9odprj-ap6so8?file=app%2Fmain.jsx
From what I noticed, the issue occurs because the selectedRowArray appears empty once a checkbox is deselected:
const SelectCell = props => {
const selectRow = !isEmpty(find(selectedRowsArray, item => item.id === props.dataItem.id)) ? find(selectedRowsArray, item => item.id === props.dataItem.id).selected : props.dataItem.selected
if
(!isEmpty(selectedRowsArray)) {
selectedRowsArray = filterList(selectedRowsArray, item => item.selected)
}
console.log(selectedRowsArray, props.dataItem.selected)
As this has a lot of custom code, I will need more time to check the internal logic to see why this occurs. Sharing the internal idea of this logic, could prove helpful for me to observe it.
Also, as a side suggestion it could be more easier to control it if there is a single place that holds the selected values instead of relaying on both props from the parent and the dataItem prop.
For example an array holding the Ids which will be populated by the props and updated when a checkbox is selected. Similar to what is done here:
https://stackblitz.com/edit/react-valgmy-9yp1gm?file=app/main.jsx
Regards,
Stefan
Progress Telerik
Hi Stefan, the idea of the grid is to behave as follows.
- Filtering
- Selection
- If headerSelectBox is checked without any filters, it should return the whole dataset to the parent.
- If headerSelectBox is checked with any filters, it should return the dataset corresponding to the filters to the parent (no pagelimit).
- If headerSelectBox is checked with any filters, and filter criteria is changed by even a character, headerSelectBox should be unchecked whereas previous seleced items should still be checked.
- I also need a functionality to send in preselected rows from the parent, which should default be checked and return the checked rows back again to the parent through a callback.
- I can also modify the preselected rows (unchecking) as well as check new items and the new selected list should be sent through a callback.
- Ability to implement custom checkboxes rather than kendo one's.
- One small issue I encountered is that I am unable to pass the event from the headerSelectBox to the method (headerSelectionChange). This is why I introduced a global variable and modified it.
I was able to achieve all of this somehow (hacks ofcourse) except point 5. It still partially works but if you can help me debug uncheck a single items when two or more preselected values come in, that will be great.
Hi Stefan,
I implemented the functionality in a more cleaner way based on your advice.
https://stackblitz.com/edit/react-valgmy-w8ihb8?file=app/main.jsx
Is there any way I can skip having a global value change when I click on header checkbox?
If the referred global variable is "selectAllValue", it can be replaced with the logic that we have used in the example:
headerSelectionValue={
this
.state.products.data[0] !== undefined &&
this
.state.products.data.findIndex(dataItem => dataItem.selected ===
false
) === -1
} // the logic has to be modified to the real application
Instead to the "headerSelectionValue" of the select column it can be added to the checked property of the checkbox used for the header. This will determine based on the current data, if the headerCheckBox has to be checked or not.
Regards,
Stefan
Progress Telerik
Hi Stefan,
For some reason, that didnt quite work well.
do you mind if you can help me out on fixing the row checkbox click in the link below?
https://stackblitz.com/edit/react-9odprj-ap6so8?file=app%2Fmain.jsx
If I have multiple items checked, and I try to unselect one everything gets unchecked.
There are my findings:
The issue occurs because on line 224 we set the selected value to false when making the "newSelectedRows" array:
else
{
newSelectedRows = [...selectedRows, Object.assign(event.dataItem, {selected:
false
})]
Then when we call filterList on the selected items, the item that has to be selected is removed as its selected prop is already set to false:
if
(!isEmpty(selectedRowsArray)) {
selectedRowsArray = filterList(selectedRowsArray, item => item.selected)
}
This leads to the case where we end up with no selected items in the "selectedRowsArray". Which then results in no selected items in the Grid.
Please check the logic executed in "selectionChange" to observe why the selected prop of the dataItem is set to false based on the if statements.
I hope these finding will lead you in the right direction.
Regards,
Stefan
Progress Telerik
@Stefan
I fixed it this way.
https://stackblitz.com/edit/react-9odprj?file=app%2Fmain.jsx
Thanks a lot for your help. Please let me know if I can optimize the useEffect code for filter in a more better way.
I'm glad that this is fix.
As for a better approach, there are many things to consider, as this will be placed inside an bigger application with its own logic.
If I made a suggestion based on this, it may not be the best one considering the big picture.
Regards,
Stefan
Progress Telerik