Skip to content

Add vanilla js for add a collection element #15455

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 20, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 34 additions & 56 deletions form/form_collections.rst
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ On the rendered page, the result will look something like this:

.. code-block:: html

<ul class="tags" data-prototype="&lt;div&gt;&lt;label class=&quot; required&quot;&gt;__name__&lt;/label&gt;&lt;div id=&quot;task_tags___name__&quot;&gt;&lt;div&gt;&lt;label for=&quot;task_tags___name___name&quot; class=&quot; required&quot;&gt;Name&lt;/label&gt;&lt;input type=&quot;text&quot; id=&quot;task_tags___name___name&quot; name=&quot;task[tags][__name__][name]&quot; required=&quot;required&quot; maxlength=&quot;255&quot; /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;">
<ul class="tags" data-index="{{ form.tags|length > 0 ? form.bars|last.vars.name + 1 : 0 }}" data-prototype="&lt;div&gt;&lt;label class=&quot; required&quot;&gt;__name__&lt;/label&gt;&lt;div id=&quot;task_tags___name__&quot;&gt;&lt;div&gt;&lt;label for=&quot;task_tags___name___name&quot; class=&quot; required&quot;&gt;Name&lt;/label&gt;&lt;input type=&quot;text&quot; id=&quot;task_tags___name___name&quot; name=&quot;task[tags][__name__][name]&quot; required=&quot;required&quot; maxlength=&quot;255&quot; /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;">

.. seealso::

Expand Down Expand Up @@ -290,19 +290,9 @@ functionality with JavaScript:

.. code-block:: javascript

jQuery(document).ready(function() {
// Get the ul that holds the collection of tags
var $tagsCollectionHolder = $('ul.tags');
// count the current form inputs we have (e.g. 2), use that as the new
// index when inserting a new item (e.g. 2)
$tagsCollectionHolder.data('index', $tagsCollectionHolder.find('input').length);

$('body').on('click', '.add_item_link', function(e) {
var $collectionHolderClass = $(e.currentTarget).data('collectionHolderClass');
// add a new tag form (see next code block)
addFormToCollection($collectionHolderClass);
})
});
document
.querySelectorAll('.add_item_link')
.forEach(btn => btn.addEventListener("click", addFormToCollection));

The ``addFormToCollection()`` function's job will be to use the ``data-prototype``
attribute to dynamically add a new form when this link is clicked. The ``data-prototype``
Expand All @@ -312,34 +302,23 @@ you'll replace with a unique, incrementing number (e.g. ``task[tags][3][name]``)

.. code-block:: javascript

function addFormToCollection($collectionHolderClass) {
// Get the ul that holds the collection of tags
var $collectionHolder = $('.' + $collectionHolderClass);

// Get the data-prototype explained earlier
var prototype = $collectionHolder.data('prototype');
const addFormToCollection = (e) => {
const collectionHolder = document.querySelector('.' + e.currentTarget.dataset.collectionHolderClass);

// get the new index
var index = $collectionHolder.data('index');
const item = document.createElement('li');

var newForm = prototype;
// You need this only if you didn't set 'label' => false in your tags field in TaskType
// Replace '__name__label__' in the prototype's HTML to
// instead be a number based on how many items we have
// newForm = newForm.replace(/__name__label__/g, index);
item.innerHTML = collectionHolder
.dataset
.prototype
.replace(
/__name__/g,
collectionHolder.dataset.index
);

// Replace '__name__' in the prototype's HTML to
// instead be a number based on how many items we have
newForm = newForm.replace(/__name__/g, index);
collectionHolder.appendChild(item);

// increase the index with one for the next item
$collectionHolder.data('index', index + 1);

// Display the form in the page in an li, before the "Add a tag" link li
var $newFormLi = $('<li></li>').append(newForm);
// Add the new form at the end of the list
$collectionHolder.append($newFormLi)
}
collectionHolder.dataset.index++;
};

Now, each time a user clicks the ``Add a tag`` link, a new sub form will
appear on the page. When the form is submitted, any new tag forms will be converted
Expand Down Expand Up @@ -552,36 +531,35 @@ First, add a "delete this tag" link to each tag form:

.. code-block:: javascript

jQuery(document).ready(function() {
// Get the ul that holds the collection of tags
$collectionHolder = $('ul.tags');

// add a delete link to all of the existing tag form li elements
$collectionHolder.find('li').each(function() {
addTagFormDeleteLink($(this));
});

// ... the rest of the block from above
});
const tags = document.querySelectorAll('ul.tags')
tags.forEach((tag) => {
addTagFormDeleteLink(tag)
})

// ... the rest of the block from above

function addFormToCollection() {
// ...

// add a delete link to the new form
addTagFormDeleteLink($newFormLi);
addTagFormDeleteLink(item);
}

The ``addTagFormDeleteLink()`` function will look something like this:

.. code-block:: javascript

function addTagFormDeleteLink($tagFormLi) {
var $removeFormButton = $('<button type="button">Delete this tag</button>');
$tagFormLi.append($removeFormButton);
const addTagFormDeleteLink = (tagFormLi) => {
const removeFormButton = document.createElement('button')
removeFormButton.classList
removeFormButton.innerText = 'Delete this tag'

tagFormLi.append(removeFormButton);

$removeFormButton.on('click', function(e) {
removeFormButton.addEventListener('click', (e) => {
e.preventDefault()
// remove the li for the tag form
$tagFormLi.remove();
tagFormLi.remove();
});
}

Expand Down Expand Up @@ -677,7 +655,7 @@ the relationship between the removed ``Tag`` and ``Task`` object.

.. _`Owning Side and Inverse Side`: https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/unitofwork-associations.html
.. _`jQuery`: http://jquery.com/
.. _`JSFiddle`: http://jsfiddle.net/847Kf/4/
.. _`JSFiddle`: https://jsfiddle.net/ey8ozh6n/
.. _`@a2lix/symfony-collection`: https://github.com/a2lix/symfony-collection
.. _`symfony-collection`: https://github.com/ninsuo/symfony-collection
.. _`ArrayCollection`: https://www.doctrine-project.org/projects/doctrine-collections/en/1.6/index.html