Files
ludikevent_crm/assets/libs/RepeatLine.js
Serreau Jovann 034210d91d ```
 feat(Formules.php): Ajoute relation OneToOne avec FormulesRestriction.
 feat(Dashboard/FormulesController.php): Gère restrictions formules et formulaire.
🎨 refactor(template/formules): Améliore interface configuration restriction formule.
🐛 fix(assets/RepeatLine.js): Corrige réinitialisation TomSelect et selects "Type".
 feat(assets/initTomSelect.js): Gère cache options et init TomSelect.
```
2026-01-28 16:00:35 +01:00

128 lines
3.9 KiB
JavaScript

import { initTomSelect } from "./initTomSelect.js" // Assure-toi que le chemin est correct
export class RepeatLine extends HTMLDivElement {
connectedCallback() {
this.$props = this.getProps(this, { maxRows: 20 });
this.$refs = this.getRefs(this);
// On stocke le HTML de la première ligne comme modèle
this.rowHTML = this.$refs.rows.children[0].outerHTML;
this.init();
}
setUpRow(row) {
const rowRefs = this.getRefs(row);
if (rowRefs.removeButton) {
rowRefs.removeButton.onclick = (e) => {
e.preventDefault();
this.removeRow(row);
};
}
}
updateAddButton() {
if (this.$refs.rows.children.length >= this.$props.maxRows) {
this.$refs.addButton.setAttribute('disabled', '');
return;
}
this.$refs.addButton.removeAttribute('disabled');
}
updateFieldNames() {
[...this.$refs.rows.children].forEach((el, index) => {
el.querySelectorAll('[name]').forEach(input => {
const newName = input.getAttribute('name').replace(/\[\d+\]/gm, `[${index}]`);
input.setAttribute('name', newName);
});
});
}
addRow() {
if (!this.rowHTML || this.$refs.rows.children.length >= this.$props.maxRows) return;
let newRow = this.createFromHTML(this.rowHTML);
newRow.removeAttribute('id');
newRow.querySelectorAll('select').forEach(select => {
// 1. Si c'est un select TomSelect (sans attribut 'is')
if (!select.hasAttribute('ds')) {
select.classList.remove('tomselect', 'ts-hidden-visually');
select.innerHTML = '<option value="">Sélectionner...</option>';
const wrapper = select.nextElementSibling;
if (wrapper && wrapper.classList.contains('ts-wrapper')) {
wrapper.remove();
}
}
// 2. Si c'est votre select "Type" (avec l'attribut 'is')
else {
// On ne touche PAS au innerHTML pour garder les options (Structure, etc.)
select.value = ""; // On remet juste à zéro la sélection
}
});
this.setUpRow(newRow);
this.$refs.rows.appendChild(newRow);
// Réinitialisation des autres champs
newRow.querySelectorAll('input,textarea').forEach(el => {
el.value = "";
});
// Initialisation TomSelect uniquement sur ce qui doit l'être
initTomSelect(newRow);
this.updateFieldNames();
this.updateAddButton();
const firstInput = newRow.querySelector('input,textarea,select');
if (firstInput) firstInput.focus();
}
removeRow(row) {
if (this.$refs.rows.children.length <= 1) return;
// Détruire l'instance TomSelect pour libérer la mémoire avant de supprimer le DOM
row.querySelectorAll('select').forEach(select => {
if (select.tomselect) {
select.tomselect.destroy();
}
});
row.remove();
this.updateFieldNames();
this.updateAddButton();
}
init() {
this.setUpRow(this.$refs.rows.children[0]);
this.$refs.addButton.onclick = (e) => {
e.preventDefault();
this.addRow();
}
this.updateFieldNames();
}
getRefs(el) {
let result = {};
[...el.querySelectorAll('[data-ref]')].forEach(ref => {
result[ref.dataset.ref] = ref;
});
return result;
}
getProps(el, defaults = {}) {
return Object.assign(defaults, JSON.parse(el.dataset.props ?? '{}'));
}
createFromHTML(html = '') {
let element = document.createElement('div');
element.innerHTML = html.trim();
return element.firstElementChild;
}
}