diff --git a/js/forms/custom-elements/choices.js b/js/forms/custom-elements/choices.js index 2c0470405..6d75769ff 100644 --- a/js/forms/custom-elements/choices.js +++ b/js/forms/custom-elements/choices.js @@ -2,6 +2,10 @@ class ChoicesElement extends HTMLSelectElement { plugins = []; connectedCallback() { + if (this.tomselect) { + return; + } + if (this.getAttribute('multiple')) { this.plugins.push('remove_button'); } diff --git a/js/forms/custom-elements/collection.js b/js/forms/custom-elements/collection.js index 2e93ff95b..5a32d8666 100644 --- a/js/forms/custom-elements/collection.js +++ b/js/forms/custom-elements/collection.js @@ -7,7 +7,7 @@ class CollectionElement extends HTMLElement { customElements.define('collection-element', CollectionElement); } - static addFormToCollection(e) { + addFormToCollection(e) { const collectionHolder = document.querySelector('.'+e.currentTarget.dataset.collectionHolderClass); const item = document.createElement('div'); @@ -21,17 +21,19 @@ class CollectionElement extends HTMLElement { collectionHolder.dataset.index ); - collectionHolderList.appendChild(item); + collectionHolderList.appendChild(item.firstChild); collectionHolder.dataset.index++; + + this.querySelectorAll('collection-entry-element').forEach((entry) => { + console.log('test'); + entry.updateButtonStates(); + }); } /** connectedCallback **/ connectedCallback() { this.#eBtnAdd = this.querySelector('.add_item_link'); - this.#eBtnAdd.addEventListener('click', CollectionElement.addFormToCollection); + this.#eBtnAdd.addEventListener('click', this.addFormToCollection.bind(this)); } - #removeCollectionItem() { - - } } diff --git a/js/forms/custom-elements/collection_entry.js b/js/forms/custom-elements/collection_entry.js index 1c27b40c8..2fa5be900 100644 --- a/js/forms/custom-elements/collection_entry.js +++ b/js/forms/custom-elements/collection_entry.js @@ -1,6 +1,9 @@ class CollectionEntryElement extends HTMLElement { + // Button elements #eBtnDelete; + #eBtnMoveUp; + #eBtnMoveDown; // register the custom element static { @@ -9,11 +12,96 @@ class CollectionEntryElement extends HTMLElement { /** connectedCallback **/ connectedCallback() { - this.#eBtnDelete = this.querySelector('.remove_item_link'); - this.#eBtnDelete.addEventListener('click', this.#removeCollectionItem.bind(this)); + + if ((this.dataset.new || this.dataset.allowDelete) && this.#eBtnDelete === undefined) { + this.#eBtnDelete = this.#createButton('Delete', 'ibo-button ibo-is-regular ibo-is-danger'); + this.#eBtnDelete.addEventListener('click', this.#removeCollectionItem.bind(this)); + this.appendChild(this.#eBtnDelete); + } + + if (this.dataset.allowOrdering) { + if (this.#eBtnMoveUp === undefined) { + this.#eBtnMoveUp = this.#createButton('Move Up', 'ibo-button ibo-is-regular'); + this.#eBtnMoveUp.addEventListener('click', this.#moveUp.bind(this)); + this.appendChild(this.#eBtnMoveUp); + } + if (this.#eBtnMoveDown === undefined) { + this.#eBtnMoveDown = this.#createButton('Move Down', 'ibo-button ibo-is-regular'); + this.#eBtnMoveDown.addEventListener('click', this.#moveDown.bind(this)); + this.appendChild(this.#eBtnMoveDown); + } + } + + this.updateButtonStates(); } - #removeCollectionItem(e) { + /** + * Update the state of the buttons (enabled/disabled). + * + */ + updateButtonStates() { + + if(this.previousElementSibling === null) { + this.#eBtnMoveUp.setAttribute('disabled', 'disabled'); + } + else{ + this.#eBtnMoveUp.removeAttribute('disabled'); + } + + if(this.nextElementSibling === null) { + this.#eBtnMoveDown.setAttribute('disabled', 'disabled'); + } + else{ + this.#eBtnMoveDown.removeAttribute('disabled'); + } + } + + /** + * Create a button element. + * + * @param label + * @param className + * @returns {HTMLButtonElement} + */ + #createButton(label, className) { + + const btnElement = document.createElement('button'); + btnElement.type = 'button'; + btnElement.className = className; + btnElement.textContent = label; + + return btnElement; + } + + /** + * Move this collection item up. + * + */ + #moveUp() { + const prev = this.previousElementSibling; + if (prev) { + this.parentNode.insertBefore(this, prev); + prev.updateButtonStates(); + } + } + + /** + * Move this collection item down. + * + */ + #moveDown() { + const next = this.nextElementSibling; + if (next) { + this.parentNode.insertBefore(next, this); + next.updateButtonStates(); + } + } + + /** + * Remove this collection item. + * + */ + #removeCollectionItem() { this.remove(); } } diff --git a/js/forms/forms.js b/js/forms/forms.js index d26dfde84..61fd8ec31 100644 --- a/js/forms/forms.js +++ b/js/forms/forms.js @@ -15,7 +15,7 @@ function triggerTurbo(el) { el.form.setAttribute('novalidate', true); el.form.requestSubmit(); el.form.querySelector(`[name="${sFormName}[_turbo_trigger]"]`).value = null; - el.form.setAttribute('novalidate', false); + el.form.removeAttribute('novalidate'); $aFormBlockDataTransmittedData[name] = el.value; } diff --git a/sources/Forms/FormType/Base/CollectionFormType.php b/sources/Forms/FormType/Base/CollectionFormType.php index e28d14555..7130be43f 100644 --- a/sources/Forms/FormType/Base/CollectionFormType.php +++ b/sources/Forms/FormType/Base/CollectionFormType.php @@ -34,6 +34,7 @@ class CollectionFormType extends AbstractType $resolver->setDefaults([ 'button_label' => 'Add an item', + 'allow_ordering' => false, ]); } @@ -43,6 +44,7 @@ class CollectionFormType extends AbstractType parent::buildView($view, $form, $options); $view->vars['button_label'] = $options['button_label']; + $view->vars['allow_ordering'] = $options['allow_ordering']; } } diff --git a/templates/application/forms/itop_console_layout.html.twig b/templates/application/forms/itop_console_layout.html.twig index 59ad45c03..e37c47441 100644 --- a/templates/application/forms/itop_console_layout.html.twig +++ b/templates/application/forms/itop_console_layout.html.twig @@ -81,24 +81,18 @@ {%- block collection_widget -%} {% if prototype is defined and not prototype.rendered %} - {% set deleteBtn = '' %} - {%- set prototype_html = '' ~ form_widget(prototype) ~ ' ' ~ deleteBtn ~'' -%} + {%- set prototype_html = '' ~ form_widget(prototype) ~'' -%} {%- set attr = attr|merge({'data-prototype': prototype_html, 'class': name, 'data-index': form|length > 0 ? form|last.vars.name + 1 : 0 }) -%} {% endif %} - {% if allow_add %} {% endif %} -
{% for child in form %} - + {{ form_widget(child) }} - {% if allow_delete %} - - {% endif %} {% endfor %}