オートコンプリートでフィールドシティを使ってみました。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));
}
}