-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
[Form] Twig example of personalized embed collection #6321
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
Conversation
Th3Mouk
commented
Mar 2, 2016
Q | A |
---|---|
Doc fix? | no |
New docs? | yes |
Applies to | all |
Fixed tickets | none |
@@ -1574,6 +1574,15 @@ are 4 possible *parts* of a form that can be rendered: | |||
|
|||
.. note:: | |||
|
|||
The portion corresponding to ``collection`` type is ``entry``. | |||
In the case of embed collections, for exemple, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
embed collections
-> embedded collections
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for exemple
-> for example
@Th3Mouk there are some minor typos to fix, but I like your proposal. Thanks for contributing to Symfony! |
@javiereguiluz thanks for support ! |
in a form which you have a year which contains months, and months contains days. | ||
You want to personalize each collection render, where the form prefix is ``_my_form_year``, | ||
you need to write two blocks, ``_my_form_year_months_entry_row`` to customize month render, and | ||
``_my_form_year_months_entry_days_entry_row`` for days inputs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be honest, I do not really understand this addition. To which entry
do we refer here? And what do we understand by "a year which contains months, and months contains days"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its an example on multiple embedded collections, a form which contains a collectiontype, which contains himself an other collectiontype. If you have an idea for a better explanation, it would help.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have the code of the example you have in mind? If I completely understand what you are thinking about I can hopefully suggest something that is (as I think) a bit easier to understand (maybe it's sufficient to provide some more details).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class CalendrierExerciceType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('periodeSemaines', CollectionType::class, [
'label' => false,
'entry_type' => PeriodeSemaineType::class,
'entry_options' => ['saison' => $options['saison']],
'by_reference' => false,
'allow_add' => true,
'prototype_name' => '__periode__',
])
;
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'saison' => null,
'data_class' => 'Entities\ElcaBundle\Entity\CalendrierExercice',
));
}
}
namespace AppBundle\Form\Type;
use Entities\ElcaBundle\Repository\PeriodeRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PeriodeSemaineType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('periode', EntityType::class, [
'class' => 'Entities\ElcaBundle\Entity\Periode',
'choice_label' => 'libelle',
'query_builder' => function (PeriodeRepository $em) use ($options) {
return $em
->createQueryBuilder('p')
->join('p.saison', 's')
->where('s.id = :id_saison')
->setParameter('id_saison', $options['saison']->getId())
;
},
'attr' => [
'data-select2-perso' => true,
],
])
->add('semaines', CollectionType::class, [
'entry_type' => SemaineZoneType::class,
'by_reference' => false,
'allow_add' => true,
'prototype_name' => '__semaine__',
])
;
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Entities\ElcaBundle\Entity\PeriodeSemaine',
'saison' => null,
));
}
}
namespace AppBundle\Form\Type;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class SemaineZoneType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('startDate', DateType::class, [
'label' => 'Date de début',
'widget' => 'single_text',
'format' => 'dd/MM/yyyy',
])
->add('endDate', DateType::class, [
'label' => 'Date de fin',
'widget' => 'single_text',
'format' => 'dd/MM/yyyy',
])
->add('zones', EntityType::class, [
'class' => 'Entities\ElcaBundle\Entity\Zone',
'choice_label' => 'libelle',
'multiple' => true,
'required' => false,
'attr' => [
'data-select2-perso' => true,
],
])
;
}
/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'Entities\ElcaBundle\Entity\Semaine',
));
}
}
{% block _calendrier_exercice_periodeSemaines_entry_row %}
<div class="row periode">
<div class="col-xs-2">
{{ form_row(form.periode) }}
</div>
<div class="col-xs-10">
{{ form_errors(form.semaines) }}
{{ form_label(form.semaines) }}<a href="#" data-add-week style="color: green;"> <i class="fa
fa-plus-circle"></i></a>
{{ form_widget(form.semaines) }}
</div>
</div>
{% endblock %}
{% block _calendrier_exercice_periodeSemaines_entry_semaines_entry_row %}
<div class="row semaine">
<div class="col-xs-4">
{{ form_row(form.startDate) }}
</div>
<div class="col-xs-4">
{{ form_row(form.endDate) }}
</div>
<div class="col-xs-4">
{{ form_row(form.zones) }}
</div>
</div>
{% endblock %}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Th3Mouk Those are nice examples! However I suggest minor things if they should go in the docs:
- utiliser des noms de classes et d'options en anglais "saison => season",
- actually
PeriodeSemaineType
may break-
This is a good opportunity to show some option resolving as default for "saison" option is null but you call
$options['saison']->getId()
You should have inconfigureOptions
$resolver->setDefaults(array( 'data_class' => 'Entities\ElcaBundle\Entity\PeriodeSemaine', 'saison' => 'null', 'query_builder' => function (Options $options) { // make it lazy $saison = $options['saison']; if (null === $saison || !$saison instanceof Saison) { return null; } return function (PeriodeRepository $em) use ($saison) { return $em ->createQueryBuilder('p') ->leftJoin('p.saison', 's') ->select('p, s') ->where('s.id = :id_saison') ->setParameter('id_saison', $saison->getId()) ; }; }, ));
- Btw
CalendrierExerciceType
only needs to have$resolver-setDefined('saison')
as a "child" option it needs no default value, only to be passed to the child which will resolve it.
- Btw
-
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if the whole code must be added to documentation, but it's an example of what i've didn't find in the customization doc.
I am totally going nuts with this collection type! I renamed my parent form to mainForm, and when I try to use
I am showing the comment lines too because I want you to see what I've tried, the local variable inside the block |
@twify93 your issue is that you use |
OK, so simple example which can work? I've moved the theme block to another file, but now it's just ignoring it... It's like I am not getting the name of the row I want to override.. |
Well, have you updated your |
I'm closing this because we couldn't merge it on time and meanwhile, the docs about this "fragment naming" have been improved a lot. See https://symfony.com/doc/current/form/form_themes.html#form-fragment-naming Thank you all for the discussion. |