Symfony 2 GenemuFormBundle如何用Ajax创建jQuery Select2

我正在尝试使用GenemuFormBundle添加一个Select2输入,如“使用带有Ajax的jQuery Select2”文档中所述。 在jQuery Select2 Field文档之后添加一个jQuery Select2字段工作得很好。

但是关于如何实现Ajax加载Select2表单的文档是非常不确定的。 如果我正确地打开文档,它的目标是创建Select2文档中提到的相同内容。 这正是我想要创建的。 我添加了隐藏字段以及所需的JavaScript,但我唯一得到的是一个Variable "id" does not exist in xBundle:x:new.html.twig at line x

表单构建器(直接从上述文档中获取):

...
->add('field_name', 'genemu_jqueryselect2_hidden', array(
    'configs' => array(
        'multiple' => true // Wether or not multiple values are allowed (default to false)
    )
))
->add('field_name', 'genemu_jqueryselect2_entity', array(
    'class' => 'xBundle:Entity',
    'property' => 'foo',
))

查看(也直接从文档中获取):

{% block stylesheets %}
    {{ form_stylesheet(form) }}
{% endblock %}

{% block javascript %}
    {{ form_javascript(form) }}
{% endblock %}

{% block genemu_jqueryselect2_javascript %}

    <script type="text/javascript">
        $field = $('#{{ id }}');

        var $configs = {{ configs|json_encode|raw }};

        // custom configs
        $configs = $.extend($configs, {
            query: function (query) {
                var data = {results: []}, i, j, s;
                for (i = 1; i < 5; i++) {
                    s = "";
                    for (j = 0; j < i; j++) {s = s + query.term;}
                    data.results.push({id: query.term + i, text: s});
                }
                query.callback(data);
            }
        });
        // end of custom configs

        $field.select2($configs);
    </script>

{% endblock %}

我只是在为这个确切的问题而努力,并认为我会将自己的发现发布给任何碰巧遇到这种情况的人。 我找到了一个解决方案,但是我可能仍然会推荐使用Doug推荐的ZenStruckFormBundle,因为它似乎实际上被设计为用于通过ajax加载并且与实体相关的select2字段类型的解决方案。

这是行不通的真正原因是genemu_jqueryselect2_*类型没有实现数据转换器,当您需要ajax-loading select2字段时,它将与实体一起工作。 它似乎并没有被设计成以这种方式工作。 当您使用genemu_jqueryselect2_hidden类型并将“多个”配置选项设置为true时,它会添加一个ArrayToStringTransformer。 这不适用于实体。

为了解决这个问题,你需要创建一个新的表单字段类型,并定义它的父类是genemu_jqueryselect2_hidden然后进行一些自定义。 它看起来像这样...

namespace AcmeDemoBundleFormType;

use SymfonyComponentFormAbstractType;
use SymfonyComponentFormFormBuilderInterface;
use AcmeDemoBundleFormDataTransformerEntityCollectionToIdTransformer;
use DoctrineCommonPersistenceObjectManager;
use SymfonyComponentOptionsResolverOptionsResolverInterface;

class EntityCollectionSelectorType extends AbstractType
{
    /**
     * @var ObjectManager
     */
     protected $om;

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

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $transformer = new EntityCollectionToIdTransformer($this->om, $options['configs']['entity']);
        $builder->resetViewTransformers();
        $builder->addModelTransformer($transformer);
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'invalid_message' => 'The selected entity does not exist',
            'required' => true,
            'auto_initialize' => false,
            'configs' => array('multiple' => true),
            'error_bubbling' => false, 
        ));
    }

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

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

然后,您还需要添加上述表单字段类型中使用的新数据转换器,以便它可以转换表单字段和实体之间的值。

namespace AcmeDemoBundleFormDataTransformer;

use SymfonyComponentFormDataTransformerInterface;
use SymfonyComponentFormExceptionTransformationFailedException;
use DoctrineORMPersistentCollection;
use DoctrineCommonPersistenceObjectManager;
use DoctrineCommonCollectionsArrayCollection;

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

    /**
     * @var string The Doctrine entity type to use
     */
    private $entityType;

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

    /**
     * Transforms a collection of entities to a comma separated string
     *
     * @param  ArrayCollection $entities
     * @return string
     */
    public function transform($entities)
    {
        if (null == $entities || empty($entities)) {
            return '';
        }

        $results = '';
        foreach ($entities as $entity) {
            $results .= $entity->getId() . ',';
        }
        $results = trim($results, ' ,');

        return $results;
    }

   /**
    * Transforms a string of comma separated IDs to a PersistentCollection for Doctrine
    *
    * @param  string $values
    * @return PersistentCollection|ArrayCollection
    * @throws TransformationFailedException if entity is not found.
    */
    public function reverseTransform($values)
    {
        if (!$values) {
            return new ArrayCollection();
        }
        $values = explode(',', $values);

        $collection = array();
        foreach ($values as $id) {
            $item = $this->om->getRepository($this->entityType)->findOneById($id);

            if (!is_null($item)) {
                $collection[] = $item;
            }
            else {
                throw new TransformationFailedException(sprintf(
                    'An entity with ID "%s" does not exist!',
                    $value
                ));
            }
        }

        return new PersistentCollection($this->om, $this->entityType, new ArrayCollection($collection));
    }
}

现在确保你在配置中为你的服务定义了新的字段类型......

<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

    <parameters>
        ...
        <parameter key="acme_demo.form.type.entity_collection_selector.class">AcmeDemoBundleFormTypeEntityCollectionSelectorType</parameter>
        ...
    </parameters>

    <services>
        ...
        <service id="acme_demo.form.type.entity_collection_selector"
            class="%acme_demo.form.type.entity_collection_selector.class%">
            <argument type="service" id="doctrine.orm.default_entity_manager" />
            <tag name="form.type" alias="entity_collection_selector" />
        </service>
        ...
    </services>
</container>

现在你可以使用它...

$builder->add('customers', 'entity_collection_selector', array(
    'configs' => array('entity' => 'AcmeDemoBundle:Customer')
));
链接地址: http://www.djcxy.com/p/78391.html

上一篇: Symfony 2 GenemuFormBundle how to create a jQuery Select2 with Ajax

下一篇: include: onload calling a function defined in included controller