Как добавить выбор в select после загрузки страницы в symfony2
После загрузки страницы поле выбора динамически заполняется jquery, но данные поста не загружаются в $form->getData(). После некоторого поиска можно добавить скрытое поле и добавить значение с помощью javascript. Я хотел бы знать, существует ли другой вариант.
Это действие:
$form = $this->createFormBuilder()
->add('country','file')
->add('admcod2','file')
->add('isocountry', 'choice', array('empty_value' => 'select country'))
->add('iso','hidden')
->getForm();
Выбор заполнен jquery
$("#form_isocountry").jeoCountrySelect({
callback: function () {
$("#form_isocountry").removeAttr('disabled');
}
});
//this add the value to a hidden field...
$("#form_isocountry").change(function() {
$("#form_iso").val($("#form_isocountry").val());
})
Таким образом, Symfony не распознает параметры, загруженные в динамических выборках. var_dump($form->getData()) показывает скрытое заполненное поле, но не поле выбора.
Благодарю.
2 ответа
Я полагаю, что choice
это неправильный тип поля для этого варианта использования, потому что с точки зрения поля формы список возможных вариантов выбора пуст. Поэтому представленное значение никогда не будет действительным (кроме случаев, когда оно пустое).
Я могу предложить вам использовать hidden
как тип этого поля или указать список вариантов для вашего поля формы с choice
тип.
Я использовал ChoiceType
поля таким образом. Я думаю, что это логичный выбор. Основная проблема с ним (и по умолчанию EntityToIdTransformer
или же EntityChoiceList
является то, что он гидратирует все возможные варианты, чтобы выбрать один, который в некоторых случаях является избыточным. Вы, вероятно, должны написать свой собственный преобразователь, чтобы предотвратить это. Я использую AJAX для загрузки данных в селекторы после загрузки страницы. Это делает страницы меньше, ускоряет время обработки страницы и позволяет мне более точно кэшировать каждый набор параметров.
Это для Symfony 2.0. Он работает нормально, и мы поместили кучу полей Chosen на одну страницу с 4000+ опциями в них (хотя он создает элементы Chosen только тогда, когда пользователь взаимодействует с виджетом). Теперь ограничением является память браузера.
ContactEntityType
class ContactEntityType extends AbstractType {
public function __construct(EntityManager $em) {
$this->em = $em;
}
public function buildForm(FormBuilder $builder, array $options)
{
$repository = $this->em->getRepository('AcmeContactsBundle:Contact');
$builder->prependClientTransformer(new ContactToIdTransformer($repository));
}
public function buildView(FormView $view, FormInterface $form)
{
$contact = $form->getData();
if($contact instanceof \Acme\ContactsBundle\Entity\Contact) {
$view->set('choices', array($contact->getId() => $contact->getName()));
}
}
public function getParent(array $options) {
return 'choice';
}
}
ContactToIdTransformer
Это вариант встроенного EntityToIdTransformer
,
...
class ContactToIdTransformer implements DataTransformerInterface
{
private $repository;
public function __construct(EntityRepository $repository)
{
$this->repository = $repository;
}
public function transform($entity)
{
if (null === $entity || '' === $entity) {
return null;
}
if (!is_object($entity)) {
throw new UnexpectedTypeException($entity, 'object');
}
if ($entity instanceof Collection) {
throw new \InvalidArgumentException('Expected an object, but got a collection. Did you forget to pass "multiple=true" to an entity field?');
}
return $entity->getId();
}
public function reverseTransform($key)
{
if ('' === $key || null === $key) {
return null;
}
if (!is_numeric($key)) {
throw new UnexpectedTypeException($key, 'numeric');
}
if (!($entity = $this->repository->find($key))) {
throw new TransformationFailedException(sprintf('The entity with key "%s" could not be found', $key));
}
return $entity;
}
}