Bug #103971
closedAjax-dispatcher.ts fails to load all stylesheets when they are loaded through an inline-relation in backend
100%
Description
We have a configuration in the backend. Where we have an accordion that can have multiple accordion items. Each accordion item can have multiple buttons. When you add a button to an accordion item, you can also select an icon for in that button. The icon can be selected using an custom styled input select.
When you open the accordion item, it will try to load all js and css required by the module. These are loaded dynamically through an ajax request. `ajax-dispather.ts` is used here to inject the relevant stylesheets. In my example it uses the following stylesheets.
[
"/_assets/937be57c7660e085d41e9dabf38b8aa1/Css/editor.css?1710839460",
"/_assets/f5f6d48c4a9e67b540bea426607200c5/CSS/iconField.css"
],
The issue is that only the first stylesheet is injected into the dom. So we're missing out on iconField.css.
I've debugged the issue, and found a bug in ajax-dispatcher.ts. And specifically in the function `processResponse`.
Here it's going wrong:
if (json.stylesheetFiles) {
for (const [index, stylesheetFile] of json.stylesheetFiles.entries()) {
if (!stylesheetFile) {
break;
}
const element = document.createElement('link');
element.rel = 'stylesheet';
element.type = 'text/css';
element.href = stylesheetFile;
document.querySelector('head').appendChild(element);
json.stylesheetFiles.splice(index, 1);
}
}
the line: json.stylesheetFiles.splice(index, 1); splices out an item from the array. But it modifies the array which is being looped through. This causes sideeffects. Which causes it to only inject the first item from the looped array.
The following code should fix it:
if (json.stylesheetFiles && json.stylesheetFiles.length) {
const copyStylesheetFiles = [...json.stylesheetFiles];
for (const stylesheetFile of copyStylesheetFiles.values()) {
if (!stylesheetFile) {
break;
}
const element = document.createElement('link');
element.rel = 'stylesheet';
element.type = 'text/css';
element.href = stylesheetFile;
document.querySelector('head').appendChild(element);
json.stylesheetFiles.splice(json.stylesheetFiles.indexOf(stylesheetFile), 1);
}
}
I've created some unit tests, to replicate the issue.
https://playcode.io/1894374
Updated by Andreas Kienast 6 months ago
- Status changed from New to In Progress
- Is Regression changed from No to Yes
Updated by Andreas Kienast 6 months ago
- Related to Task #103375: Implement `@typescript-eslint/no-array-delete` rule added
Updated by Gerrit Code Review 6 months ago
- Status changed from In Progress to Under Review
Patch set 1 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/84487
Updated by Gerrit Code Review 6 months ago
Patch set 1 for branch 12.4 of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/84488
Updated by Andreas Fernandez 6 months ago
- Status changed from Under Review to Resolved
- % Done changed from 0 to 100
Applied in changeset b2654761be234449b2335127dfa5798c88e70a55.