Fix race condition in ChillCollectionType

In some dcase, the collection is not initialized when a showHide is launched before the collection is fully initialized.
This commit is contained in:
Julien Fastré 2024-10-15 09:08:29 +02:00
parent 1313b6f138
commit 13dbbb6741
Signed by: julienfastre
GPG Key ID: BDE2190974723FCB
4 changed files with 37 additions and 4 deletions

View File

@ -36,6 +36,7 @@ class ChillCollectionType extends AbstractType
$view->vars['identifier'] = $options['identifier']; $view->vars['identifier'] = $options['identifier'];
$view->vars['empty_collection_explain'] = $options['empty_collection_explain']; $view->vars['empty_collection_explain'] = $options['empty_collection_explain'];
$view->vars['js_caller'] = $options['js_caller']; $view->vars['js_caller'] = $options['js_caller'];
$view->vars['uniqid'] = uniqid();
} }
public function configureOptions(OptionsResolver $resolver) public function configureOptions(OptionsResolver $resolver)

View File

@ -30,6 +30,12 @@
*/ */
import './collection.scss'; import './collection.scss';
declare global {
interface GlobalEventHandlersEventMap {
'show-hide-show': CustomEvent<{id: number, froms: HTMLElement[], container: HTMLElement}>,
}
}
export class CollectionEventPayload { export class CollectionEventPayload {
collection: HTMLUListElement; collection: HTMLUListElement;
entry: HTMLLIElement; entry: HTMLLIElement;
@ -107,20 +113,34 @@ export const buildRemoveButton = (collection: HTMLUListElement, entry: HTMLLIEle
return button; return button;
} }
window.addEventListener('load', () => { const collectionsInit = new Set<string>;
const buttonsInit = new Set<string>();
const initialize = function (target: Document|Element): void {
let let
addButtons: NodeListOf<HTMLButtonElement> = document.querySelectorAll("button[data-collection-add-target]"), addButtons: NodeListOf<HTMLButtonElement> = document.querySelectorAll("button[data-collection-add-target]"),
collections: NodeListOf<HTMLUListElement> = document.querySelectorAll("ul[data-collection-regular]"); collections: NodeListOf<HTMLUListElement> = document.querySelectorAll("ul[data-collection-regular]");
for (let i = 0; i < addButtons.length; i++) { for (let i = 0; i < addButtons.length; i++) {
let addButton = addButtons[i]; const addButton = addButtons[i];
const uniqid = addButton.dataset.uniqid as string;
if (buttonsInit.has(uniqid)) {
continue;
}
buttonsInit.add(uniqid);
addButton.addEventListener('click', (e: Event) => { addButton.addEventListener('click', (e: Event) => {
e.preventDefault(); e.preventDefault();
handleAdd(e.target); handleAdd(e.target);
}); });
} }
for (let i = 0; i < collections.length; i++) { for (let i = 0; i < collections.length; i++) {
let entries: NodeListOf<HTMLLIElement> = collections[i].querySelectorAll(':scope > li'); const collection = collections[i];
const uniqid = collection.dataset.uniqid as string;
if (collectionsInit.has(uniqid)) {
continue;
}
collectionsInit.add(uniqid);
let entries: NodeListOf<HTMLLIElement> = collection.querySelectorAll(':scope > li');
for (let j = 0; j < entries.length; j++) { for (let j = 0; j < entries.length; j++) {
if (entries[j].dataset.collectionEmptyExplain === "1") { if (entries[j].dataset.collectionEmptyExplain === "1") {
continue; continue;
@ -128,4 +148,13 @@ window.addEventListener('load', () => {
initializeRemove(collections[i], entries[j]); initializeRemove(collections[i], entries[j]);
} }
} }
};
window.addEventListener('DOMContentLoaded', () => {
initialize(document);
}); });
window.addEventListener('show-hide-show', (event: CustomEvent<{id: number; container: HTMLElement; froms: HTMLElement[]}>) => {
const container = event.detail.container as HTMLElement;
initialize(container);
})

View File

@ -47,7 +47,7 @@ window.addEventListener('DOMContentLoaded', function() {
// ShowHide instance for send external // ShowHide instance for send external
new ShowHide({ new ShowHide({
debug: true, debug: false,
load_event: null, load_event: null,
froms: [divTransitions], froms: [divTransitions],
container: [sendExternalContainer], container: [sendExternalContainer],

View File

@ -163,6 +163,7 @@
<div class="chill-collection"> <div class="chill-collection">
<ul class="list-entry" <ul class="list-entry"
{{ form.vars.js_caller }}="{{ form.vars.js_caller }}" {{ form.vars.js_caller }}="{{ form.vars.js_caller }}"
data-uniqid="{{ form.vars.uniqid|escape('html_attr') }}"
data-collection-name="{{ form.vars.name|escape('html_attr') }}" data-collection-name="{{ form.vars.name|escape('html_attr') }}"
data-collection-identifier="{{ form.vars.identifier|escape('html_attr') }}" data-collection-identifier="{{ form.vars.identifier|escape('html_attr') }}"
data-collection-button-remove-label="{{ form.vars.button_remove_label|trans|e }}" data-collection-button-remove-label="{{ form.vars.button_remove_label|trans|e }}"
@ -184,6 +185,8 @@
{% if form.vars.allow_add == 1 %} {% if form.vars.allow_add == 1 %}
<button class="add-entry btn btn-misc" <button class="add-entry btn btn-misc"
type="button"
data-uniqid="{{ form.vars.uniqid|escape('html_attr') }}"
data-collection-add-target="{{ form.vars.name|escape('html_attr') }}" data-collection-add-target="{{ form.vars.name|escape('html_attr') }}"
data-form-prototype="{{ ('<div>' ~ form_widget(form.vars.prototype) ~ '</div>')|escape('html_attr') }}" > data-form-prototype="{{ ('<div>' ~ form_widget(form.vars.prototype) ~ '</div>')|escape('html_attr') }}" >
<i class="fa fa-plus fa-fw"></i> <i class="fa fa-plus fa-fw"></i>