title: How to get data in a form event within a CollectionType?
body: <p>I have a problem with Symfony 4 on an issue already identified and described on Github (here: <a href="https://github.com/symfony/symfony/issues/5694#issuecomment-110398953" rel="nofollow noreferrer">https://github.com/symfony/symfony/issues/5694#issuecomment-110398953</a>) but I can't find a way to apply this answer.</p>
  
  <p>When I try to use a POST_SET_DATA form event in a ChildType form, the function getData() gives me a null value because the "allow_add" option is set on true in the ParentType form which is a CollectionType.</p>
  
  <p>I have 3 collections: Page, Moduling and Module. The Moduling document is used to embed a collection of Module forms. The purpose is to be able to add multiple forms to the Page collection with one request, following this Symfony article: <a href="https://symfony.com/doc/current/form/form_collections.html" rel="nofollow noreferrer">https://symfony.com/doc/current/form/form_collections.html</a>.</p>
  
  <p>I have 2 different embedded documents: Tag and Task. Both of them are embedded in the Module document (EmbedOne). What I want to do is to be able to custom the ModuleType field with a form event listener so that I just need to set the title of the Module in the controller and then Symfony knows it needs to use the TaskType or the TagType within the ModuleType. </p>
  
  <p>So first, here is my controller</p>
  
  <pre><code>class TaskingController extends Controller
  {
      /**
       * The controller from which I set the module title, "task" here
       *
       * @Route("/{slug}/task/create", name="tasking_create")
       * 
       * @ParamConverter("page", options={"mapping": {"slug": "slug"}})
       * 
       * @return Response
       */
      public function createTasking(DocumentManager $dm, $id, Module $module, Moduling $moduling)
      {
          $page = $dm-&gt;find(Page::class, $id);
  
          $module-&gt;setTitle('task');
  
          $moduling-&gt;addModule($module);
          $page-&gt;addModuling($moduling);
  
          $form = $this-&gt;createForm(ModulingType, $moduling);
          $form-&gt;handleRequest($request);
  
          if ($form-&gt;isValid() &amp;&amp; $form-&gt;isSubmitted() {
              // Form validation then redirection
          }
          // Render form template}
      }
  }
  </code></pre>
  
  <p>Now, here are my three collections: pages, moduling and modules</p>
  
  <pre><code>/**  
   * My page document
   *
   * @MongoDB\Document(collection="pages")
   */
  class Page
  {
      /** 
       * @MongoDB\Id(strategy="AUTO")
       */
      protected $id;
  
      /**
       * @MongoDB\ReferenceMany(targetDocument="App\Document\Moduling")
       * 
       * @var Moduling
       */
      protected $moduling = array();
  
      public function __construct()
      {
          $this-&gt;moduling = new ArrayCollection();
      }
  
      /**
       * Get the value of id
       */ 
      public function getId()
      {
          return $this-&gt;id;
      }
  
      /**
       * @return Collection $moduling
       */    
      public function getModuling()
      {
          return $this-&gt;moduling;
      }
  
      /**
       * @param Moduling $moduling
       */
      public function addModuling(Moduling $moduling)
      {
          $this-&gt;moduling[] = $moduling;
      }
  
      /**
       * @param Moduling $moduling
       */
      public function removeModuling(Moduling $moduling)
      {
          $this-&gt;moduling-&gt;removeElement($moduling);
      }
  }
  
  /**
   * @MongoDB\Document(collection="moduling")
   */
  class Moduling
  {
      /**
       * @MongoDB\Id(strategy="AUTO")
       */
      protected $id;
  
      /**
       * @MongoDB\ReferenceOne(targetDocument="App\Document\Page", storeAs="id")
       * 
       * @var Page
       */
      protected $parentPage;
  
      /**
       * @MongoDB\ReferenceMany(targetDocument="App\Document\Module", mappedBy="moduling")
       */
      protected $module = array();
  
      public function __construct()
      {
          $this-&gt;module = new ArrayCollection();
      }
  
      /**
       * Get the value of id
       */
      public function getId()
      {
          return $this-&gt;id;
      }
  
      public function getModule()
      {
          return $this-&gt;module;
      }
  
      public function addModule(Module $module): self
      {   
          $this-&gt;module[] = $module;
      }
  
      public function removeModule(Module $module)
      {
          $this-&gt;module-&gt;removeElement($module);
      }
  
      /**
       * Get the value of parentPage
       *
       * @return  Page
       */ 
      public function getParentPage()
      {
          return $this-&gt;parentPage;
      }
  
      /**
       * Set the value of parentPage
       *
       * @param  Page  $parentPage
       *
       * @return  self
       */ 
      public function setParentPage(Page $parentPage)
      {
          $this-&gt;parentPage = $parentPage;
  
          return $this;
      }
  }
  
  /**  
   * @MongoDB\Document(collection="modules")
   */
  class Module
  {
      /**
       * @MongoDB\Id(strategy="AUTO")
       */
      public $id;
  
      /**
       * @MongoDB\Field(type="string")
       */
      public $title;
  
      /**
       * @MongoDB\ReferenceOne(targetDocument="App\Document\Moduling", inversedBy="module", storeAs="id")
       */
      public $moduling;
  
      /**
       * @MongoDB\EmbedOne(targetDocument="App\Document\Task", strategy="set")
       * @Assert\Valid
       */
      public $task;
  
      public function getTitle()
      {
          return $this-&gt;title;
      }
  
      /**
       * @return  self
       */ 
      public function setTitle($title)
      {
          $this-&gt;title = $title;
  
          return $this;
      }
  
      public function getTask()
      {
          return $this-&gt;task;
      }
  
      public function setTask(Task $task = null)
      {
          $this-&gt;task = $task;
      }
  }
  </code></pre>
  
  <p>My embedded document Task. The Tag document has the same structure.</p>
  
  <pre><code>/**  
   * @MongoDB\EmbeddedDocument
   */
  class Task
  {
      /**
       * @MongoDB\Id(strategy="AUTO")
       */
      protected $id;
  
      public function getId()
      {
          return $this-&gt;id;
      }
  }
  </code></pre>
  
  <p>My ModulingType, which is a collection of ModuleType</p>
  
  <pre><code>class ModulingType extends AbstractType
  {
      public function buildForm(FormBuilderInterface $builder, array $options)
      {
          $builder
              -&gt;add('module', CollectionType::class, [
                  'entry_type' =&gt; ModuleType::class,
                  'entry_options' =&gt; [
                      'label' =&gt; false,
                  ],
                  'by_reference' =&gt; false,
                  'allow_add' =&gt; true,
                  'allow_delete' =&gt; true
                  ])
          ;
      }
  
      public function configureOptions(OptionsResolver $resolver)
      {
          $resolver-&gt;setDefaults([
              'data_class' =&gt; Moduling::class
          ]);
      }
  }
  
  class ModuleType extends AbstractType
  {
      public function buildForm(FormBuilderInterface $builder, array $options)
      {
          $builder-&gt;addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) {
              $module = $event-&gt;getData();
              $form = $event-&gt;getForm();
  
              if ('task' == $module-&gt;getTitle()) {
                  $form-&gt;add('task', TaskType::class);
              }
          });
      }
  
      public function configureOptions(OptionsResolver $resolver)
      {
          $resolver-&gt;setDefaults([
              'data_class' =&gt; Module::class
          ]);
      }
  }
  </code></pre>
  
  <p>So I have identified the problem. When I try to make this work, Symfony sends me this error message: "Call to a member function getTitle() on null". It seems the getData() doesn't get anything. </p>
  
  <p>Actually, after reading few posts on Github I've realized that the "allow_add" option set on "true" was the origin of this issue. And indeed, when I set it on "false" I don't have any error message. But the consequence of this is that my JQuery doesn't allow me to duplicate the form if I want to, the "allow_add" option is necessary to do that.</p>
  
  <p>In the Github post I uploaded, they say that the solution is to write this code first in the ModuleType:</p>
  
  <pre><code>$builder-&gt;addEventListener(FormEvents::POST_SET_DATA, function (FormEvent $event) {
      if (null != $event-&gt;getData()) {
      }
  }
  </code></pre>
  
  <p>It's what I did but it doesn't change anything. I wrote this, followed by the code written in the ModuleType but I still have the same error message... Perhaps I don't know how to insert it correctly in the ModuleType.</p>
  
  <p>I hope someone has a solution. I know I can still add the Tag and Task types directly in the ModulingType but I would have more collections.</p>
  
  <p>Thanks a lot for helping me, I hope I've been clear enough!</p>
  
  <p>Cheers</p>