2012-02-24 2 views
2

Мне нужна помощь с прототипами, которые находятся в прототипах. Symfony очень умна с созданием прототипов форм, но как только вы один слой вниз (то есть прототипы внутри прототипов), он повторно использует $$ name $$ для обоих прототипов.

Это то, что поле прототипа выглядит для моего объекта. JQuery свопы из $$ имя $$ с правильным значением индекса (на основе количества дочерних узлов)

<input type="text" id="entry_entities_$$name$$_contactFax" name="entry[entities][$$name$$][contactFax]" value="" /> 

До сих пор так хорошо. Но когда вы идете один уровень глубже, Symfony использует $$ имя $$ для следующего уровня вниз тоже - вот прототип для свойства объекта:

<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) что все свойства получить ID 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 $$ на каждой строке, но он стал очень грязным. Я уверен, что есть простой способ сделать это, но я не мог найти никаких гидов в Интернете.

+0

Вы передаете функцию $$ name $$ в функции prototype(), разве вы не можете ее там изменить? – meze

+2

На самом деле я заглянул в код Symfony после публикации этого. $$ name $$ жестко закодировано в CollectionType. Взгляните на Symfony \ Component \ Form \ Extension \ Core \ Type \ CollectionType.php – mogoman

+2

Право. [Не жестко закодирован в 2.1] (https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Form/Extension/Core/Type/CollectionType.php). – meze

ответ

5

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

+0

отлично, спасибо! – mogoman

+0

Я видел этот ответ через 3 дня, пытаясь переписать и разграничить заполнители. Хотелось бы, чтобы я это видел раньше. +10000000! – renoirb

+0

@renoirb Хорошо! Но имейте в виду, что это взлом для 2.0. Поскольку v2.1 вы можете просто передать имя функции 'prototype()'. – meze

0

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

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

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

+0

Спасибо за ответ - я считаю, что ваша идея сработала бы, но результатом было бы много Javascript. Ответ Мезе подходит к лучшей практике Symfony2. – mogoman

+0

Достаточно честно :) В основном размещен как опция, ожидая, что кто-то придумает решение, соответствующее Symfony. Рад, что у вас есть способ, которым вы довольны, – Joe

Смежные вопросы