Bonjour,

J'ai un formulaire dans lequel se trouve une collection, et chaque élément de celle-ci contient aussi un collection.
Mon formulaire est correctement créé.

Nom : 2015-12-03 15_44_13- edit a node type.png
Affichages : 786
Taille : 10,0 Ko

Par exemple, pour le champ minC (cfr plus bas classe StringFieldParameters), j'ai le code html suivant
Code : Sélectionner tout - Visualiser dans une fenêtre à part
<input type="text" id="form_fields_0_parameters_0_min" name="form[fields][0][parameters][0][min]" value="0">

Je peux ajouté des champs supplémentaires via le bouton "Add a field", ... tout ça marche très bien.
J'ai un peu souci pour récupérer les valeurs de la collection se trouvant dans la collection


Voici mon controleur ou je créée le formulaire et traite les valeurs encodées par celui-ci.

Le problème se situe à ligne 53 dans la classe BackendNodeTypeController

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
class BackendNodeTypeController extends \Fmk\CoreBundle\Controller\BackendController 
{
...
 
public function updateAction(Request $request, $nodeTypeId) 
{
        $em = $this->getEntityManager();
 
        $nodeType = $em->find('Fmk\CmsBundle\Entity\NodeType', $nodeTypeId);
        if ($nodeType !== null)
        {
            // **************************** DECLARATION DU FORMULAIRE **************************** 
            $formManageNodeType = $this->createFormBuilder($nodeType)
                ->add('name', 'text')
                ->add('label', 'text')
                ->add('namespace', 'text')
                ->add('description', 'textarea',array('required' => false,))
            ;
 
            $formManageNodeType->add('fields', 'collection', array(
                'type' => new NodeTypeFieldType(),
                'allow_add' => true,
                'allow_delete' => true,
                'by_reference' => false,
                'prototype' => true,
                'attr' => array('class'=>'nodeType-field'),
            ));
 
            $formManageNodeType->add('save', 'submit', array('label' => 'Save'))
            ->add('saveAndquit', 'submit', array('label' => 'Save and quit'));
 
            $formManageNodeType = $formManageNodeType->getForm();
 
 
            // **************************** SAUVEGARDE DU FORMULAIRE **************************** 
            $formManageNodeType->handleRequest($request);
 
            if ($formManageNodeType->isValid()) {
                $data = $formManageNodeType->getData();
 
                $position = 0;             
                foreach ($nodeType->getFields() as $key => &$field) 
                {
                    $parameters = array();
 
                    $fields = $formManageNodeType->get('fields');
 
                    foreach ($fields as $key => $value) {
                        // J'obtiens corretement les valeurs de la collection "fields" associée à la classe NodeTypeFieldType (cfr un peu plus haut)
                        $f = $value->getData();
                        // je récupère la valeurs de la collection parameters
                        $p = $value->get('parameters')->getData();
                        //PROBLEME -----------> p est tjs vide <----------
 
                    }                    
                    $field->setName(StringHandler::camelCase($field->getName()));
                    $field->setPosition($position++);
                    $field->setNodeType($nodeType);
                    $field->setParameters($parameters);
                    $em->persist($field);
                    if (false == $nodeType->getFields()->contains($field)) 
                    {
                        $nodeType->addField($field);
                    } 
                }
                $em->persist($nodeType);
                $em->flush();
                if ($formManageNodeType->get('save')->isClicked()) 
                return $this->redirectToRoute('cmsBackendUpdateNodeType', array('nodeTypeId'=>$nodeType->getID()));
                else//if ($formManageNodeType->get('saveAndquit')->isClicked()) 
                return $this->redirectToRoute('cmsBackendNodeTypeDefault');
 
            }
 
            $this->assignation['formManageNodeType'] = $formManageNodeType->createView();
 
            //$prototype = $this->assignation['formManageNodeType']->children['fields']->vars['prototype'];
            $this->assignation['nodeType'] = $nodeType;
            return $this->render('FmkCmsBundle:Backend:NodeType/add.html.twig', $this->assignation);
        }
        else {
            return $this->throw404();
        }
    }
    ...
}


La classe fmk/cmsbundle/form/type/NodeTypeFieldType.php

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?php
namespace Fmk\CmsBundle\Form\Type;
 
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Fmk\CmsBundle\Entity\NodeTypeField;
 
class NodeTypeFieldType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
 
        //http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html
        //http://stackoverflow.com/questions/19730051/how-to-embed-a-precharged-collection-of-non-entity-forms-in-symfony2
        $formModifier = function (&$form, $data=null) {
            if($data){
                $parameters = $data->getParameters();
                $type = $data->getType();
                $form->remove("parameters");
 
                switch ($type) {
                    case NodeTypeField::STRING_TYPE :
                    default:
                        $classe = new \Fmk\CmsBundle\Form\Type\StringFieldParameters();
                        break;
                }
 
                $form->add("parameters", 'collection', array(
                    "label" => false,
                    "mapped" => true,
                    'data_class' => null,
                    "prototype" => false,
                    'type' => $classe,
                    'by_reference' => false,
                    'options' => array('label' => false),
                    'data' => array($parameters),
                ));
            }
        };
        $builder->addEventListener(
            FormEvents::PRE_SET_DATA,
            function (FormEvent $event) use ($formModifier) {
                $data = $event->getData();
                $form = $event->getForm();
                $formModifier($form, $data);
            }
        );
        $builder->add('name', 'text',array('required' => true,));
        $builder->add('label', 'text',array('required' => true,));
        $builder->add('type', 'choice',array(
            'label' => 'type', 
            'required' => true,
            'choices' =>NodeTypeField::$typeToHuman,
            'attr' => array('class'=>'nodeTypesList'),
        ));
    }
 
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Fmk\CmsBundle\Entity\NodeTypeField',
            'allow_extra_fields' => true,
        ));
    }
 
    public function getName()
    {
        return 'NodeTypeField';
    }
}
La classe fmk/cmsbundle/form/type/StringFieldParameters.php

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?php
namespace Fmk\CmsBundle\Form\Type;
 
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
 
class StringFieldParameters extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event){
            $form = $event->getForm();
            //$form = $event->getForm()->getParent();
            $data = $event->getData(); 
 
            if(!$data){
                return;
            } 
            else {
                $form->add('min', 'integer',array('label' => 'minU', 'data'=>isset($data['min']) ? $data['min'] : 0, 'required' => false,));
                $form->add('max', 'integer',array('label' => 'maxU', 'data'=>isset($data['max']) ? $data['max'] : 255, 'required' => false,)); 
            }
 
         });
        $builder->add('min', 'text',array('label' => 'minC', 'required' => false, 'data'=>0));
        $builder->add('max', 'text',array('label' => 'maxC', 'required' => false,  'data'=>255));
    }
 
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'allow_extra_fields' => true,
        ));
    }
 
    public function getName()
    {
        return 'StringFieldParameters';
    }
}


merci pour votre aide,
Philippe