Skip to content

Instantly share code, notes, and snippets.

@Maxooo
Last active August 29, 2015 14:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Maxooo/85b67f72ec3840464c4e to your computer and use it in GitHub Desktop.
Save Maxooo/85b67f72ec3840464c4e to your computer and use it in GitHub Desktop.
Symfony2 - Handle collection type prototype in twig with jquery
{% block stylesheet %}
<script src="{{ asset("js/jquery.collection.js") }}"></script>
{% endblock %}
{% block body %}
<h1>{{ "Form with an addresses collection" }}</h1>
<form action="{{ path('route') }}" method="post" {{ form_enctype(form) }}>
{{ form_row(form.firstname) }}
{{ form_row(form.lastname) }}
{{ form_row(form.birthDate) }}
{#{ form_row(form.whateverYouWant }#}
<hr />
<div class="collection" id="{{ "address" }}" data-prototype="{{ _self.address(form.addresses.vars.form.vars.prototype)|escape }}">
{% for address in form.addresses.vars.form.children %}
{{ _self.address(address) }}
{% endfor %}
</div>
<a href="#" onClick="javascript: return false;" class="{{ "add-item" }}">
{{ "Add an address" }}
</a>
{% macro address(form) %}
<div class="{{ "item" }} classe classe-{{ form.vars.name }}">
<a href="#" class="{{ "remove-item" }}">
{{ "Delete this address" }}
</a>
{{ form_row(form.street) }}
{{ form_row(form.address) }}
{{ form_row(form.postalCode) }}
{{ form_row(form.city) }}
{{ form_row(form.country) }}
{#{ form_row(form.whateverYouWant }#}
</div>
<hr/>
{% endmacro %}
{{ form_rest(form) }}
</form>
{% endblock %}
{% block javascript %}
{{ parent() }}
<script type="text/javascript">
(function($){
$('.collection').collection();
})(jQuery);
</script>
{% endblock %}
/**
* jQuery Collection Plugin v1.0.0
* This class provide javascript collection handler features to dynamically add and remove elements inside a form.
*
* https://gist.github.com/Maxooo/85b67f72ec3840464c4e/edit
*
* Copyright 2013, 2014 Maxime CORSON <maxime.corson@spyrit.net>
*
* Released under the MIT license
*/
(function ($) {
$.fn.collection = function( options ) {
var defaults = {
itemSelector: '.item',
addSelector: '.add-item',
removeSelector: '.remove-item',
onAdd: function($item){},
onRemove: function(){}
};
return this.each(function() {
var $this = $(this);
var settings = $.extend(true, {}, defaults, options, $this.data());
function addAddListener()
{
$(settings.addSelector).on('click', function(e) {
var $item = addCollectionItem();
settings.onAdd($item);
});
};
function addRemoveListener()
{
$this.find(settings.removeSelector).on('click', function(e) {
$(this).parents(settings.itemSelector).remove();
settings.onRemove();
});
};
function addCollectionItem()
{
var item = $($this.attr('data-prototype').replace(/__name__/g, $this.children().length));
$this.append(item);
addRemoveListener();
return item;
};
addAddListener();
addRemoveListener();
});
};
}( jQuery ));
<?php
namespace Acme\TaskBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class UserAddressType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('street')
->add('address')
->add('postalCode')
->add('city')
->add('country')
//->add('whateverYouWant')
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\TaskBundle\Entity\UserAddress', // Propel model is better ;)
));
}
public function getName()
{
return 'address';
}
}
<?php
namespace Acme\TaskBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstname')
->add('lastname')
->add('birthDate')
->add('addresses', 'collection', array(
'type' => new Acme\TaskBundle\Form\Type\UserAddressType(),
'allow_add' => 'true',
'allow_remove' => 'true',
//'by_reference' => 'false', // Use this option if you are on Propel
))
//->add('whateverYouWant')
;
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Acme\TaskBundle\Entity\User', // Propel model is better ;)
));
}
public function getName()
{
return 'user';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment