Прототипы форм Symfony 2 внутри прототипов - двойное поле $$ name - PullRequest
2 голосов
/ 24 февраля 2012

Мне нужна помощь с прототипами, которые находятся внутри прототипов. 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="    
    &lt;label for=&quot;entry_entities_$$name$$_properties_$$name$$_name&quot;&gt;Name&lt;/label&gt;
    &lt;input type=&quot;text&quot; id=&quot;entry_entities_$$name$$_properties_$$name$$_name&quot; name=&quot;entry[entities][$$name$$][properties][$$name$$][name]&quot; value=&quot;&quot; /&gt;

Это означает, что (в этом примере с идентификатором сущности 123) все свойства получают идентификатор 123:

name="entry[entities][123][properties][123][name]"
name="entry[entities][123][properties][123][name]"
name="entry[entities][123][properties][123][name]"

и т.д.

По моему мнению, лучший способ решить эту проблему - это использовать $$ somethingelse $$ для свойства - кто-нибудь знает, где это установлено - или у кого-нибудь есть полный пример с JS, как решить эту проблему? Я начал ужасную находку / замену второго $$ name $$ в каждой строке, но это стало очень грязно. Я уверен, что есть простой способ сделать это, но я не смог найти никаких руководств в Интернете.

Ответы [ 2 ]

5 голосов
/ 24 февраля 2012

Этот код предназначен для 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.

0 голосов
/ 24 февраля 2012

Я не знаком с Symfony, но использование String.replace() в Javascript заменяет только первое вхождение по умолчанию, поэтому вы можете использовать это довольно безопасно.

$('mydiv').html
(
    $('mydiv').html().replace('$$name$$', 123).replace('$$name$$', 456);
);

Если вещи разбиты на разные строкии вы хотите заменить в этих строках, вы можете использовать .split(), чтобы разбить его на массив, for() поверх него, затем .join() снова вместе.

...