Project

General

Profile

Actions

Bug #104833

open

Recycler shows wrong number of selected records

Added by Thomas Rawiel about 2 months ago. Updated about 2 months ago.

Status:
New
Priority:
Should have
Assignee:
-
Category:
Recycler
Target version:
-
Start date:
2024-09-05
Due date:
% Done:

0%

Estimated time:
TYPO3 Version:
12
PHP Version:
8.3
Tags:
Complexity:
easy
Is Regression:
Sprint Focus:

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

recyclermiscalculated.jpg (76.8 KB) recyclermiscalculated.jpg Thomas Rawiel, 2024-09-05 12:00

Related issues 1 (0 open1 closed)

Related to TYPO3 Core - Bug #104142: Disabled checkbox state can be changed via multi record selectionClosedOliver Bartsch2024-06-18

Actions
Actions #1

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.

Actions #2

Updated by Sébastien Delcroix about 2 months ago

  • Related to Bug #104142: Disabled checkbox state can be changed via multi record selection added
Actions

Also available in: Atom PDF