我正在尝试创建自定义选项列表字段。 几乎所有看起来都有效,除了编辑部分的预选值。
基本上我正在创建一个具有多个对象类型的混合列表字段(后端是mongodb),我知道这是一种肮脏的操作方式,但我找不到更好的解决方案(保持简单)。 这个过程正常,我在后端有一个混合对象,我可以选择编辑表单中的哪一个,但表单没有显示预选(使用从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';
}
}
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;
}
}
表单构建器:
<?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';
}
}
有人遇到同样的问题吗?如何改变“选择”领域?如何在同一个字段中管理混合对象? 有人可以启发我吗?
此致
答案 0 :(得分:4)
我终于找到了解决方案。罪魁祸首是数据变换器(我当然是:-)) 通过这种方式,表单显示了预选值:
<?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;
}
}
答案 1 :(得分:0)
在大多数使用ChoiceType的情况下,transform函数返回的数组应仅包含ID。例如:
public function transform($objectsArray)
{
$choices = array();
foreach ($objectsArray as $object)
{
$choices[] = $object->getId();
}
return $choices;
}
虽然它可能不是原帖的答案,但我很确定googlers会到这里寻找这个提示。