Прототипы форм Symfony 2 внутри прототипов - двойное поле $$name
Мне нужна помощь с прототипами, которые находятся внутри прототипов. Symfony очень умен в создании прототипов форм, но как только вы окажетесь на один уровень ниже (т.е. прототипы внутри прототипов), он использует $$ name $$ для обоих прототипов.
Вот как выглядит поле прототипа для моей сущности. JQuery меняет $$ name $$ на правильное значение индекса (в зависимости от количества дочерних узлов)
<input type="text" id="entry_entities_$$name$$_contactFax" name="entry[entities][$$name$$][contactFax]" value="" />
Все идет нормально. Но когда вы идете на один уровень глубже, Symfony использует $$ name $$ и для следующего уровня ниже - вот прототип для свойства объекта:
<div id="entry_entities_123_properties" data-prototype="
<label for="entry_entities_$$name$$_properties_$$name$$_name">Name</label>
<input type="text" id="entry_entities_$$name$$_properties_$$name$$_name" name="entry[entities][$$name$$][properties][$$name$$][name]" value="" />
Это означает, что (в этом примере с идентификатором сущности 123) все свойства получают идентификатор 123:
name="entry[entities][123][properties][123][name]"
name="entry[entities][123][properties][123][name]"
name="entry[entities][123][properties][123][name]"
и т.п.
На мой взгляд, лучший способ решить эту проблему - использовать $$ что-то другое $$ для свойства - кто-нибудь знает, где это установлено - или у кого-нибудь есть полный пример с JS, как решить эту проблему? Я начал ужасную находку / замену второго $$ name $$ в каждой строке, но это стало очень грязно. Я уверен, что есть простой способ сделать это, но я не смог найти никаких руководств в Интернете.
2 ответа
Этот код предназначен для Symfony 2.0 (в 2.1+ вы можете просто передать имя prototype()
функция):
Вы можете создать свой собственный тип коллекции с необходимой опцией:
<?php
namespace YourBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilder;
use Symfony\Component\Form\FormView;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener;
use Symfony\Component\Form\Extension\Core\Type\CollectionType as BaseCollectionType;
class CollectionType extends BaseCollectionType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilder $builder, array $options)
{
if ($options['allow_add'] && $options['prototype']) {
$prototype = $builder->create($options['prototype_name'], $options['type'], $options['options']);
$builder->setAttribute('prototype', $prototype->getForm());
}
$listener = new ResizeFormListener(
$builder->getFormFactory(),
$options['type'],
$options['options'],
$options['allow_add'],
$options['allow_delete']
);
$builder
->addEventSubscriber($listener)
->setAttribute('allow_add', $options['allow_add'])
->setAttribute('allow_delete', $options['allow_delete'])
;
}
/**
* {@inheritdoc}
*/
public function getDefaultOptions(array $options)
{
$defaultOptions = parent::getDefaultOptions($options);
$defaultOptions['prototype_name'] = '$$name$$';
return $defaultOptions;
}
}
Затем просто определите сервис с помощью:
tags:
- { name: form.type, alias: collection }
И используйте его как коллекцию Symfony, но с параметром prototype_name.
Я не знаком с Symfony, но использую String.replace()
в Javascript по умолчанию заменяется только первое вхождение, так что вы можете использовать его довольно безопасно.
$('mydiv').html
(
$('mydiv').html().replace('$$name$$', 123).replace('$$name$$', 456);
);
Если вещи разбиты на разные строки, и вы хотите заменить в этих строках, вы можете использовать .split()
разбить его на массив, for()
тогда .join()
это снова вместе.