@@ -239,23 +239,31 @@ it will receive an *unknown* number of tags. Otherwise, you'll see a
239
239
The ``allow_add `` option also makes a ``prototype `` variable available to you.
240
240
This "prototype" is a little "template" that contains all the HTML needed to
241
241
dynamically create any new "tag" forms with JavaScript. To render the prototype, add
242
- the following ``data-prototype `` attribute to the existing ``<ul> `` in your template:
242
+ the following ``data-prototype `` attribute to the existing ``<ul> `` in your
243
+ template:
243
244
244
245
.. code-block :: html+twig
245
246
246
- <ul class="tags" data-index="{{ form.tags|length > 0 ? form.tags|last.vars.name + 1 : 0 }}" data-prototype="{{ form_widget(form.tags.vars.prototype)|e('html_attr') }}"></ul>
247
+ {# the data-index attribute is required for the JavaScript code below #}
248
+ <ul class="tags"
249
+ data-index="{{ form.tags|length > 0 ? form.tags|last.vars.name + 1 : 0 }}"
250
+ data-prototype="{{ form_widget(form.tags.vars.prototype)|e('html_attr') }}"
251
+ ></ul>
247
252
248
- Now add a button just next to the `` <ul> `` to dynamically add a new tag :
253
+ On the rendered page, the result will look something like this :
249
254
250
- .. code-block :: html+twig
255
+ .. code-block :: html
251
256
252
- <button type="button" class="add_item_link" data-collection-holder-class="tags">Add a tag</button>
257
+ <ul class =" tags"
258
+ data-index =" 0"
259
+ data-prototype =" < ; div> ;< ; label class=" ; required" ;> ; __name__< ; /label> ;< ; div id=" ; task_tags___name__" ;> ;< ; div> ;< ; label for=" ; task_tags___name___name" ; class=" ; required" ;> ; Name< ; /label> ;< ; input type=" ; text" ; id=" ; task_tags___name___name" ; name=" ; task[tags][__name__][name]" ; required=" ; required" ; maxlength=" ; 255" ; /> ;< ; /div> ;< ; /div> ;< ; /div> ; "
260
+ ></ul >
253
261
254
- On the rendered page, the result will look something like this :
262
+ Now add a button to dynamically add a new tag :
255
263
256
- .. code-block :: html
264
+ .. code-block :: html+twig
257
265
258
- <ul class = " tags " data-index = " 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 ; " >
266
+ <button type="button" class="add_item_link " data-collection-holder- class=" tags">Add a tag</button >
259
267
260
268
.. seealso ::
261
269
@@ -265,7 +273,7 @@ On the rendered page, the result will look something like this:
265
273
.. tip ::
266
274
267
275
The ``form.tags.vars.prototype `` is a form element that looks and feels just
268
- like the individual ``form_widget(tag) `` elements inside your ``for `` loop.
276
+ like the individual ``form_widget(tag.* ) `` elements inside your ``for `` loop.
269
277
This means that you can call ``form_widget() ``, ``form_row() `` or ``form_label() ``
270
278
on it. You could even choose to render only one of its fields (e.g. the
271
279
``name `` field):
@@ -281,18 +289,16 @@ On the rendered page, the result will look something like this:
281
289
and you need to adjust the following JavaScript accordingly.
282
290
283
291
Now add some JavaScript to read this attribute and dynamically add new tag forms
284
- when the user clicks the "Add a tag" link. This example uses `jQuery `_ and
285
- assumes you have it included somewhere on your page (e.g. using Symfony's
286
- :doc: `Webpack Encore </frontend >`).
287
-
288
- Add a ``<script> `` tag somewhere on your page to include the required
289
- functionality with JavaScript:
292
+ when the user clicks the "Add a tag" link. Add a ``<script> `` tag somewhere
293
+ on your page to include the required functionality with JavaScript:
290
294
291
295
.. code-block :: javascript
292
296
293
297
document
294
298
.querySelectorAll (' .add_item_link' )
295
- .forEach (btn => btn .addEventListener (" click" , addFormToCollection));
299
+ .forEach (btn => {
300
+ btn .addEventListener (" click" , addFormToCollection)
301
+ });
296
302
297
303
The ``addFormToCollection() `` function's job will be to use the ``data-prototype ``
298
304
attribute to dynamically add a new form when this link is clicked. The ``data-prototype ``
@@ -531,14 +537,15 @@ First, add a "delete this tag" link to each tag form:
531
537
532
538
.. code-block :: javascript
533
539
534
- const tags = document .querySelectorAll (' ul.tags li' )
535
- tags .forEach ((tag ) => {
536
- addTagFormDeleteLink (tag)
537
- })
540
+ document
541
+ .querySelectorAll (' ul.tags li' )
542
+ .forEach ((tag ) => {
543
+ addTagFormDeleteLink (tag)
544
+ })
538
545
539
546
// ... the rest of the block from above
540
547
541
- function addFormToCollection () {
548
+ const addFormToCollection = ( e ) => {
542
549
// ...
543
550
544
551
// add a delete link to the new form
@@ -549,17 +556,16 @@ The ``addTagFormDeleteLink()`` function will look something like this:
549
556
550
557
.. code-block :: javascript
551
558
552
- const addTagFormDeleteLink = (tagFormLi ) => {
553
- const removeFormButton = document .createElement (' button' )
554
- removeFormButton .classList
555
- removeFormButton .innerText = ' Delete this tag'
559
+ const addTagFormDeleteLink = (item ) => {
560
+ const removeFormButton = document .createElement (' button' );
561
+ removeFormButton .innerText = ' Delete this tag' ;
556
562
557
- tagFormLi .append (removeFormButton);
563
+ item .append (removeFormButton);
558
564
559
565
removeFormButton .addEventListener (' click' , (e ) => {
560
- e .preventDefault ()
566
+ e .preventDefault ();
561
567
// remove the li for the tag form
562
- tagFormLi .remove ();
568
+ item .remove ();
563
569
});
564
570
}
565
571
@@ -651,10 +657,9 @@ the relationship between the removed ``Tag`` and ``Task`` object.
651
657
The Symfony community has created some JavaScript packages that provide the
652
658
functionality needed to add, edit and delete elements of the collection.
653
659
Check out the `@a2lix/symfony-collection `_ package for modern browsers and
654
- the `symfony-collection `_ package based on jQuery for the rest of browsers.
660
+ the `symfony-collection `_ package based on ` jQuery `_ for the rest of browsers.
655
661
656
662
.. _`Owning Side and Inverse Side` : https://www.doctrine-project.org/projects/doctrine-orm/en/current/reference/unitofwork-associations.html
657
- .. _`jQuery` : http://jquery.com/
658
663
.. _`JSFiddle` : https://jsfiddle.net/ey8ozh6n/
659
664
.. _`@a2lix/symfony-collection` : https://github.com/a2lix/symfony-collection
660
665
.. _`symfony-collection` : https://github.com/ninsuo/symfony-collection
0 commit comments