sonja
sonja

Reputation: 934

Symfony getData event subscriber is null

I know this question has been asked already a couple of times, but there hasn't been an answer that actually helped me solving my problem.

I've got three EventSubscribers for three Dropdowns who are dependent on each other.

So in my FormType I say:

  public function buildForm(FormBuilderInterface $builder, array $options)
{
  // solution showmethecode
  $pathToAgencies = 'agencies';
  //
  $builder
    ->addEventSubscriber(new AddChannel1Subscriber($pathToAgencies))
    ->addEventSubscriber(new AddChannel3Subscriber($pathToAgencies))
    ->addEventSubscriber(new AddAgencySubscriber($pathToAgencies));

}

and one of my EventSubscribers looks like that:

    ...
...

        public static function getSubscribedEvents() {
            return array(
              FormEvents::PRE_SET_DATA  => 'preSetData',
              FormEvents::PRE_SUBMIT    => 'preSubmit'
            );
          }

          private function addChannel1Form($form, $channel1s = null) {
            $formOptions = array(
              'class' => 'AppBundle:Channel1',
                'property' => 'name',
                'label' => 'label.channel1s',
                'empty_value' => 'label.select_channel1s',
                'mapped' => false,
                'expanded' => false,
                'translation_domain' => 'UploadProfile',
                'multiple' => true,
                'required' => false,
                'attr' => array(
                  'class' => 'channel1s'
                ),
            );

            if ($channel1s){
              $formOptions['data'] = $channel1s;
            }
            $form->add('channel1s', 'entity', $formOptions);
          }

          public function preSetData(FormEvent $event) {
            $data = $event->getData();
            $form = $event->getForm();

                if (null === $data) {
                    return;
                }

            $accessor = PropertyAccess::createPropertyAccessor();
            $agency = $accessor->getValue($data, $this->pathToAgency);
            $channel1s = ($agency) ? $agency->getChannel3s()->getChannel1s() : null;
            $this->addChannel1Form($form, $channel1s);
          }

          public function preSubmit(FormEvent $event) {
            $form = $event->getForm();
            $this->addChannel1Form($form);
          }
    ...

Now I'm getting the error "Attempted to call an undefined method named "getChannel3s" of class "Doctrine\Common\Collections\ArrayCollection"." and (I think) this is because my $data in my preSetData is NULL but I don't know why it's null. Am I looking at the wrong spot or where is my mistake here?

Upvotes: 4

Views: 3449

Answers (2)

Nicolai Fröhlich
Nicolai Fröhlich

Reputation: 52513

preSetData is executed before the original data (which shall be modified if given) is bound to the form ( which is then stored in $options['data']).

The "data" in preSetData is the one you provide to createForm($type, $data = null, array $options = array()).

So before this is set -> the form obviously doesn't have any data and the event-data isn't set either. That's why $data is null inside your listener's onPreSetData method.

You're using the wrong event. Use preSubmit and build your logic around the data submitted by the user ($event->getData()). This will solve your issue.

Quick overview:

  • onPreSubmit:
    • $form->get('someButton')->isClicked() returns false
    • $event->getForm()->getData() returns $options['data'] if any or $options['empty_data']
    • $event->getData returns the submitted data (array)
    • you can use setData()
    • you can add/remove fields
  • onSubmit:
    • You can't use setData() here as data was already bound to the form
    • $form->isSubmitted() still returns false
    • $form->get('someButton')->isClicked() returns true
    • You can still add/remove fields
  • onPostSubmit:
    • $form->isSubmitted() returns true
    • "You cannot remove children from a submitted form"
    • "You cannot add children to a submitted form"
    • $form->get('someButton')->isClicked() returns true

Upvotes: 4

Athos
Athos

Reputation: 181

In the preSetData declaration you get the bad class. Try this :

public function preSetData(GenericEvent $event)

Add the next use :

use Symfony\Component\EventDispatcher\GenericEvent;

Upvotes: 0

Related Questions