Symfony2 dynamic forms mongodb
Asked Answered
H

1

1

Following the example as documented in the following http://symfony.com/doc/current/cookbook/form/dynamic_form_generation.html

I need to populate subcategory field according to the category selection. I don't understand why this error at /article/create:

FatalErrorException: Error: Call to a member function getSubCategories() on a non-object

the Form :

namespace Cc\HitoBundle\Form\Type;

…

class ArticleType extends AbstractType
{
    private $registrationArticleListener;

    public function __construct(RegistrationArticleListener $registrationArticleListener)
    {
        $this->registrationArticleListener = $registrationArticleListener;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            …

            ->add('category', 'document', array(
                'label' => 'Category',
                'class' => 'Cc\HitoBundle\Document\Category',
                'property' => 'name',
            ));


        $builder->addEventSubscriber($this->registrationArticleListener);
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Cc\HitoBundle\Document\Article'
        ));
    }

    public function getName()
    {
        return 'article';
    }
}

I don't understand what is the AddNameFieldSubscriber() function in the cookbook

The Listener:

namespace Cc\HitoBundle\Form\EventListener;

…

class RegistrationArticleListener implements EventSubscriberInterface
{
    /**
     * @var FormFactoryInterface
     */
    private $factory;

    /**
     * @var DocumentManager
     */
    private $dm;

    /**
     * @param factory FormFactoryInterface
     */
    public function __construct(FormFactoryInterface $factory, $mongo)
    {
        $this->factory = $factory;
        $this->dm = $mongo->getManager();
    }

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

    /**
     * @param event FormEvent
     */
    public function preSetData(FormEvent $event)
    {
        $agent = $event->getData();

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

        $form = $event->getForm();
        $subCategories = $article->getCategory()->getSubCategories();

        $this->customizeForm($form, $subCategories);
    }

    public function preBind(FormEvent $event)
    {
        $data = $event->getData();
        $id = $data['event'];
        $agent = $this->dm
            ->getRepository('CcHitoBundle:Article')
            ->find($id);

        if ($article === null) {
            $msg = 'The event %s could not be found for you registration';
            throw new \Exception(sprintf($msg, $id));
        }
        $form = $event->getForm();
        $subCategories = $article->getCategory()->getSubCategories();

        $this->customizeForm($form, $subCategories);
    }

    protected function customizeForm($form, $subCategories)
    {

    }
}

And I don't understand what I have to put in customizeForm function. Please help me !! =)

Holliholliday answered 12/4, 2013 at 10:0 Comment(0)
V
1

You are getting the non-object error because you are not actually creating the $article variable in your preBind or preSetData functions. It looks like you are mixing up $agent and $article

public function preSetData(FormEvent $event)
{
    //here you have $agent
    $agent = $event->getData();
    //here you have $article
    if (null === $article) {
        return;
    }

    $form = $event->getForm();
    //here you have $article
    $subCategories = $article->getCategory()->getSubCategories();

    $this->customizeForm($form, $subCategories);
}

Change to:

public function preSetData(FormEvent $event)
{
    $article = $event->getData();
    // We can only set subcategories if a category is set
    if (null === $article->getCategory()) {
        return;
    }

    $form = $event->getForm();
    //...

In customise form function you want to add the fields you need like subCategories:

//taken from the article OP referenced
protected function customizeForm($form, $subCatQueryBuilder)
{
    $formOptions = array(
        'class' => 'You\YourBundle\Entity\SubCategory',
        'multiple' => true,
        'expanded' => false,
        'property' => 'THE_FIELD_YOU_WANT_TO_SHOW',
         // I would create a query builder that selects the correct sub cats rather than pass through a collection of objects
        'query_builder' => $subCatQueryBuilder,
    );
    // create the field, this is similar the $builder->add()
    // field name, field type, data, options
    $form->add($this->factory->createNamed('subCategories', 'entity', null, $formOptions));
}

For the query builder:

/**
 * @param event FormEvent
 */
public function preSetData(FormEvent $event)
{
    $agent = $event->getData();

    if (null === $article->getCategory()) {
        return;
    }

    $form = $event->getForm();

   //Something like
   $category = $article->getCategory();
   $subCatQueryBuilder =  $this->dm
      ->getRepository("YourCatBundle:Subcategory")
      ->createQueryBuilder("sc")
      ->join("sc.category", "c")
      ->where("c.id = :category")
      ->setParameter("category", $category->getId());
   $this->customizeForm($form, $subCatQueryBuilder);
}
Vally answered 12/4, 2013 at 13:6 Comment(7)
If I have $agent It's because I made a mistake in copying and pasting, but in my project it's an article.Holliholliday
Yes so you just need to change it to $article because currently $article is not setVally
and where I have to put the query builder function ?Holliholliday
I have updated my answer, you need to pass it through to the customizeForm function so either in preSetData or put it in the subcategory repository class and return the queryBuilder object.Vally
$article = $event->getData()->getArticle() Error: Call to undefined method Cc\HitoBundle\Document\Article::getArticle()Holliholliday
let us continue this discussion in chatVally
You don't need ->getArticle() as I said because actually $event->getData() is already and Article instance, my bad. Also Click the link in my above comment to join the chatVally

© 2022 - 2024 — McMap. All rights reserved.