2

オートコンプリートでフィールドシティを使ってみました。Twitter のブートストラップ スタイルと機能の先行入力を使用していますが、自分の作業が適切かどうかはわかりません。

私の例では、Person と City (フランスの約 37,000 のコミューン) という 2 つのエンティティがあります。

Person エンティティには、City フィールド Birthplace との OneToMany 関係があります。

そこで、非表示のフィールド タイプ city_typeahead を作成して DataTransformer "CityToIdTransformer" を追加し、フォームから送信された City ID からオブジェクトを永続化します。

それまでは、オートコンプリートは作成と編集に完全に機能します。

ただし、編集フォームでは、隠しフィールドに登録されている都市の名前をオートコンプリート フィールドに表示したいと考えています。

リスナーを試してみようと思いましたが、適用する解決策がわかりません。誰かが私を導くことができれば、私は感謝します。

ありがとうございました。

編集: オートコンプリートフィールドの国で同様のテストを行い、いくつかのテストの後に到着しました。非表示フィールドに値があるかどうかを確認するリスナーを作成し、そこから名前を取得してフィールドのオートコンプリートを読み込みます。メソッドがクリーンかどうかはわかりませんが、機能します。オートコンプリート フィールドに国名が編集フォームに表示されるようになりました。

フォームタイプ:

<?php

namespace Myapp\PersonBundle\Form;

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

use Myapp\PersonBundle\Form\EventListener\AddNationalitySearchSubscriber;

class PersonType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {       
        $builder
            ->add('firstname')
            ->add('lastname')                
            ->add('nationality', 'country_typeahead', array(
                'attr' => array('class' => 'country-toset'),
                'required' => false))
            ->add('nationality_search','text', array(
            'attr' => array(
                'class' => 'country-tosearch',
                'name' => 'term',
                'autocomplete' => true,
            'required' => false,
            'mapped' => false));   

        $builder->addEventSubscriber(new AddNationalitySearchSubscriber());   
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Myapp\PersonBundle\Entity\Person'
        ));
    }

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

ビュー内のスクリプトjs:

<script type="text/javascript"> 
            $('.country-tosearch').typeahead({
                source: function(query, process){ 
                    $.ajax({
                        url: "/ajax/country",
                        type: "post",
                        data: "term="+query,
                        dataType: "json",
                        async: false,
                        success: function(data){                            
                            countries = []
                            mapped = {}                            
                            $.map(data, function(country, i){
                                mapped[country.name] = country;
                                countries.push(country.name);
                            });
                            process(countries);
                        }
                    })
                },
                minLength: 3,
                property: 'enriched',
                items:15,
                updater: function (obj) {
                    if(mapped[obj].id){
                        $('.country-toset').val(mapped[obj].id);
                    }
                    return mapped[obj].name;
                }
            });            
        </script>

データトランスフォーマー:

<?php 
namespace Myapp\PersonBundle\Form\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;

use Myapp\GeoBundle\Entity\Country;

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

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

    /**
     * Transforms an object (country) to a string (id).
     *
     * @param  Country|null $country
     * @return string
     */
    public function transform($country)
    {
        if (null === $country) {
            return "";
        }

        return $country->getId();
    }

    /**
     * Transforms a string (id) to an object (country).
     *
     * @param  string $id
     * @return Country|null
     * @throws TransformationFailedException if object (country) is not found.
     */
    public function reverseTransform($id)
    {
        if (!$id) {
            return null;
        }

        $country = $this->om
            ->getRepository('MyappGeoBundle:Country')->findOneBy(array('id' => $id))
        ;

        if (null === $country) {
            throw new TransformationFailedException(sprintf(
                'A country with id "%s" does not exist!',
                $id
            ));
        }

        return $country;
    }
}

リスナー :

<?php

namespace Myapp\PersonBundle\Form\EventListener;

use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class AddNationalitySearchSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(FormEvents::PRE_SET_DATA => 'preSetData');
    }

    public function preSetData(FormEvent $event)
    {
        $country = '';
        $data = $event->getData();
        $form = $event->getForm();

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

        if ($data->getNationality()) {
            $country = $data->getNationality();
        }

       $form->add('nationality_search','text', array(
            'attr' => array(
                'class' => 'country-tosearch',
                'name' => 'term',
                'autocomplete' => true,
            'data' => $country,
            'required' => false,
            'mapped' => false));   
    }
}
4

0 に答える 0