Bug #104833
openRecycler shows wrong number of selected records
0%
Description
In the recycler module, when you select all or just one item, the buttons for Recover and Delete show the wrong number of selected records.
In javascript the number is calculated from the elements inside the array `markedRecordsForMassAction`
The array is filled in the `handleCheckboxStateChanged`
If we look at the Developer console, we will notice CustomEvent is fired with type `"multiRecordSelection:checkbox:state:changed"` if we select a record
Depending on where we
a) correct: we click on a checkbox the event is fired once, 1 is added/substracted to/from the number in the buttons
b) wrong: we click on the record row, the click event is fired twice - 2 is added/substracted to/from the number in the buttons
I believe it has something to do with RegularEvents and the propagation of events in the markup from the table row down to the checkbox. I don't think that can be fixed very easily.
But looking at the code that handles the checkbox change event:
vendor/typo3/cms-recycler/Resources/Public/JavaScript/recycler.js
this.handleCheckboxStateChanged = e => {
const t = $(e.target), a = t.parents("tr"), s = a.data("table") + ":" + a.data("uid");
if (t.prop("checked")) this.markedRecordsForMassAction.push(s); else {
const e = this.markedRecordsForMassAction.indexOf(s);
e > -1 && this.markedRecordsForMassAction.splice(e, 1)
}
this.markedRecordsForMassAction.length > 0 ? (this.elements.$massUndo.find("span.text").text(this.createMessage(TYPO3.lang["button.undoselected"], [this.markedRecordsForMassAction.length.toString(10)])), this.elements.$massDelete.find("span.text").text(this.createMessage(TYPO3.lang["button.deleteselected"], [this.markedRecordsForMassAction.length.toString(10)]))) : this.resetMassActionButtons()
}
we see, that it is checked if the clicked element is in the array if we uncheck a checkbox, so if the element should be removed from the array.
This explains, why the following scenario happens (also: How to reproduce this bug )
- Create a page with one content element.
- Delete that content element
- Switch to the recycler module
- Alternate between clicking the record row and unchecking the checkbox multiple time
- Observe the numbers in the Recover and Delete buttons rising
Possible solution:
It has to be checked if the selected element is already available in the `markedRecordsForMassAction` array:
const j = this.markedRecordsForMassAction.indexOf(s);
if (t.prop("checked")) {
j < 0 && this.markedRecordsForMassAction.push(s);
} else {
j > -1 && this.markedRecordsForMassAction.splice(j, 1)
}
Files
Updated by Sébastien Delcroix about 2 months ago · Edited
This commit added a dispatch to 'change' Event to multi-record-selection : https://github.com/TYPO3/typo3/blob/d9323c00a3f61cfc142b598a63205f433b50971b/Build/Sources/TypeScript/backend/multi-record-selection.ts#L86 just before dispatching the 'multiRecordSelection:checkbox:state:changed' CustomEvent.
[...]
// Dispatch the standard "change" event, which might be used by form components, e.g. FormEngine
checkbox.dispatchEvent(new CustomEvent('change', { bubbles: true }));
// Dispatch custom event, which might be used by components to keep track of external state changes
checkbox.dispatchEvent(new CustomEvent('multiRecordSelection:checkbox:state:changed',{
detail: { identifier: MultiRecordSelection.getIdentifier(checkbox) }, bubbles: true, cancelable: false
}));
But the 'change' event is registered by 'registerDispatchCheckboxStateChangedEvent()' and already dispatches the 'multiRecordSelection:checkbox:state:changed' CustomEvent :
private registerDispatchCheckboxStateChangedEvent(): void {
new RegularEvent('change', (e: Event, target: HTMLInputElement): void => {
target.dispatchEvent(new CustomEvent('multiRecordSelection:checkbox:state:changed',{
detail: { identifier: MultiRecordSelection.getIdentifier(target) }, bubbles: true, cancelable: false
}));
}).delegateTo(document, MultiRecordSelectionSelectors.checkboxSelector);
}
Thus the 'multiRecordSelection:checkbox:state:changed' is dispatched twice, so the callback when clicking on a table row in the recycler module too.
Maybe the second dispatch of 'multiRecordSelection:checkbox:state:changed' is no more useful and we can just remove it.
Updated by Sébastien Delcroix about 2 months ago
- Related to Bug #104142: Disabled checkbox state can be changed via multi record selection added