3

I'm trying to create a custom choice list field. And almost all seems working, except the preselected values on the edit part.

Basically i'm creating a mixed list field with multiple object type (the backend is mongodb), i know that is a dirty way to operate but i didn't find a better solution (keeping things simple). The process is working, i have a mixed objects in the backend and i can choose which one in the edit form, but the form doesn't show the preselected (with the values extracted from mongo)

<?php
namespace www\DefaultBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use www\DefaultBundle\Form\DataTransformer\AccessorioTransformer;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class AccessorioType extends AbstractType
{
    /**
     * @var ObjectManager
     */
    private $om;

    /**
     * @param ObjectManager $om
     */
    public function __construct(ObjectManager $om)
    {
        $this->om = $om;
    }


    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $transformer = new AccessorioTransformer($this->om);
        $builder->addModelTransformer($transformer);
    }


    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $choices = array();
        $data = array();
        $documents = array(
            'Document1',
            'Document2',
            'Document3',
            );

        foreach ($documents as $document)
        {
            $objects = $this->om->getRepository('wwwDefaultBundle:' . $document)->findAll();
            foreach ($objects as $object)
            {
               if (@!$object->getId()) print_r($object);
               $key = sprintf("%s_%s", $object->getId(), basename(str_replace('\\', '/', get_class($object))));
               $value = sprintf("%s (%s)", $object, basename(str_replace('\\', '/', get_class($object))));
               $choices[$key] = $value;
            }
        }

        $resolver->setDefaults(array(
            'choices'  => $choices,
            'expanded' => false,
            'multiple' => true,
        ));

    }


    public function getParent()
    {
        return 'choice';
    }

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

the datatransformer:

<?php
namespace www\DefaultBundle\Form\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Extension\Core\ObjectChoiceList;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;
use Acme\TaskBundle\Entity\Issue;

class AccessorioTransformer implements DataTransformerInterface
{
    /**
     * @var ObjectManager
     */
    private $om;

    /**
     * @param ObjectManager $om
     */
    public function __construct(ObjectManager $om)
    {
        $this->om = $om;
    }


    public function transform($values)
    {
        return array();
        // i tried everything here but none working

    }


    public function reverseTransform($values)
    {
        if (!$values) return null;

        $array = array();

        foreach ($values as $value)
        {
          list($id, $type) = explode("_", $value);
          $array[] = $this->om->getRepository('wwwDefaultBundle:' . $type)->find($id);
        }

        return $array;
    }
}

the form builder:

<?php

namespace www\DefaultBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class ValvolaType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder

            // [snip]

            ->add('ref',
                'accessorio',
                array(
                    'label_attr' => array('class' => 'control-label col-sm-2'),
                    'attr'       => array('class' => 'form-control '),
                ))
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'www\DefaultBundle\Document\Valvola',
            'attr'       => array('class' => 'press form-horizontal'),
        ));
    }

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

Did someone faced the same problem? How "choice" field should be transformed? How managed mixed object in the same field? Someone can enlighten me?

Regards

m47730
  • 2,061
  • 2
  • 24
  • 30
  • Sigh, I'm having the same issue. Try editing your question with more information or try to make it more clear. This will "bump" your question rather than you having to delete and remake your question. It's your only option since you don't have reputation to give away for bounty yet... – Tek Jul 10 '14 at 21:04

2 Answers2

4

I finally found the solution. The culprit was the datatransformer (and mine, of course :-)) In this way the form shows the preselected values:

<?php
namespace www\DefaultBundle\Form\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Extension\Core\ObjectChoiceList;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;
use Acme\TaskBundle\Entity\Issue;

class AccessorioTransformer implements DataTransformerInterface
{
    /**
     * @var ObjectManager
     */
    private $om;

    /**
     * @param ObjectManager $om
     */
    public function __construct(ObjectManager $om)
    {
        $this->om = $om;
    }


    public function transform($values)
    {
        if ($values === null) return array();

        $choices = array();
        foreach ($values as $object)
        {
           $choices[] = sprintf("%s_%s", $object->getId(), basename(str_replace('\\', '/', get_class($object))));
        }

        return $choices;
    }


    public function reverseTransform($values)
    {
        if (!$values) return array();

        $array = array();

        foreach ($values as $value)
        {
          list($id, $type) = explode("_", $value);
          $array[] = $this->om->getRepository('wwwDefaultBundle:' . $type)->find($id);
        }

        return $array;
    }
}
m47730
  • 2,061
  • 2
  • 24
  • 30
0

In most cases using ChoiceType the array returned by the transform function should contain the ID's only. For example:

public function transform($objectsArray)
{
    $choices = array();

    foreach ($objectsArray as $object)
    {
       $choices[] = $object->getId();
    }

    return $choices;
}

Although it might not be the answer to the original post, I am pretty sure that googlers get here and look for this hint.

Jorr.it
  • 1,222
  • 1
  • 14
  • 25