-->

如何在Symfony2的形式增加collection中自动完成字段,并使用波轮?(How to ad

2019-07-30 23:47发布

我使用Symfony的2.1形式与PropelBundle和我试图重构一种形式,它有对象(从选择),而不是使用一个jQuery自动完成字段(AJAX工作)的下拉列表。 对于下拉列表中我用下面的代码(这非常完美的下拉列表)在我的表单类型:

$builder->add('books', 'collection', array(
    'type'          => 'model',
    'options'       => array(
        'class'     => 'MyVendor\MyBundle\Model\Book',
        'property'  => 'title',
    ),
    'allow_add'     => true,
    'allow_delete'  => true,
    'by_reference'  => false,
    'required'      => false,
));

对于给一点背景知识的缘故,让我们说,我们正在创造一个新的“阅读器”对象,我们想从现有的“书”对象的列表中选择读者喜爱的书籍。 使用集合类型,这样多的“最喜爱的书”可以在新的“阅读器”的形式进行选择。 现在,我想更改上述使用自动完成。 这样做,我试图执行一个数据转换器,能够从一个简单的文本字段取一本书的对象是可用于自动完成功能来传递簿ID为表示对这个问题的答案 。 然而,我无法弄清楚如何使集合类型,推动类的数据转换器的工作。 我创建了一个BookToIdTransformer类如Symfony的食谱指示,试图在“ReaderType”文件如下:

$transformer = new BookToIdTransformer();
$builder->add(
        $builder->create('books', 'collection', array(
            'type'          => 'text',
            'allow_add'     => true,
            'allow_delete'  => true,
            'by_reference'  => false,
            'required'      => false,
        ))->addModelTransformer($transformer)
);

通过上述,我得到一个“调用未定义的方法:的getId”异常(显然变压器预计书籍,而不是一个单一的图书对象的PropelCollection ..)。 有谁知道如何做呢? 还是让我知道,如果有其他的方法来实现自动完成中的Symfony使用的Propel,并允许选择多个对象(如藏书)?

Answer 1:

我最终还是去了解决的办法是从我以前的答案稍有不同。 最后我用一个“文本”字段类型,而不是在我的“ReaderType”形式的“集合”字段类型,因为我结束了使用循环J Tokeninput jQuery插件,它允许选择多个对象(例如,“最喜欢的书”)关联在形式我的主要对象(例如“读者”对象)。 考虑到,我创建了一个“数据转换器”,用于将对象的IDS通过(在文本字段用英文逗号分隔)到波轮对象集合。 代码共享如下,包括样品Ajax对象控制器。

在“ReaderType”形式的重要组成部分如下所示:

$transformer = new BooksToIdsTransformer();
$builder->add(
    $builder->create('books', 'text', array(
        'required' => false,
    ))->addModelTransformer($transformer)
);

“数据变压器”文件是这样的:

// src/MyVendor/MyBundle/Form/DataTransformer/BooksToIdsTransformer.php
namespace MyVendor\MyBundle\Form\DataTransformer;

use \PropelObjectCollection;
use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use MyVendor\MyBundle\Model\BookQuery;

class BooksToIdsTransformer implements DataTransformerInterface
{
    public function transform($books)
    {
        if (null === $books) {
            return "";
        }

        if (!$books instanceof PropelObjectCollection) {
            throw new UnexpectedTypeException($books, '\PropelObjectCollection');
        }
        $idsArray = array();
        foreach ($books as $book) {
            $idsArray[] = $book->getId();
        }
        $ids = implode(",", $idsArray);
        return $ids;
    }

    public function reverseTransform($ids)
    {
        $books = new PropelObjectCollection();

        if ('' === $ids || null === $ids) {
            return $books;
        }

        if (!is_string($ids)) {
            throw new UnexpectedTypeException($ids, 'string');
        }
        $idsArray = explode(",", $ids);
        $idsArray = array_filter ($idsArray, 'is_numeric');
        foreach ($idsArray as $id) {
            $books->append(BookQuery::create()->findOneById($id));
        }
        return $books;
    }
}

返回的“书”一个JSON收集到Tokeninput自动完成功能Ajax控制器如下:

namespace MyVendor\MyBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use MyVendor\MyBundle\Model\BookQuery;


class ClassAjaxController extends Controller
{
    public function bookAction(Request $request)
    {
        $value = $request->get('q');

        $books = BookQuery::create()->findByName('%'.$value.'%');

        $json = array();
        foreach ($books as $book) {
            $json[] = array(
                'id' => $book->getId(),
                'name' => $book->getName()
            );
        }

        $response = new Response();
        $response->setContent(json_encode($json));

        return $response;
    }
}

最后,在“修改routing.yml”文件中的路由器:

ajax_book:
    pattern:  /ajax_book
    defaults: { _controller: MySiteBundle:ClassAjax:book }


文章来源: How to add an autocomplete field in a Symfony2 form for a collection and using Propel?