web-dev-qa-db-ja.com

symfony2複数のネストされたフォームのプロトタイプ

コレクションタイプを別のコレクションタイプ内に含めたい。次のようになります。 enter image description here

コレクションを1つだけ使用しても問題ありませんが、外側のフォームのプロトタイプを編集する必要があるため、各行の内側のフォームのプロトタイプがレンダリングされます。

どうすればそれを行うことができますか?また、保存する最良の方法は何でしょうか

編集:今私はネストされたフォームのプロトタイプをレンダリングしようとしています:

  <ul class="characteristics-container" data-prototype="{{ form_widget(form.characteristics.vars.prototype)|e }}" data-prototype-options="{{ form_widget(form.characteristics.options.vars.prototype|e ) }}">
                    {# iterate over each existing tag and render its only field: name #}
                    {% for characteristic in form.characteristics %}
                        <li>{{ form_row(characteristic.name) }}</li>

                        <div class="characteristics-options">
                            {% for opt in form.characteristics.options %}

                            {% endfor %}                     
                        </div>


                    {% endfor %}
                </ul>

form_widget(form.characteristics.options.vars.prototype|eでエラーが発生します

Method "options" for object "Symfony\Component\Form\FormView" does not exist in 

私は特性[0]を試しました、そしてそれはキーが存在しないと言います

ここに私のフォームクラスがあります:

PromotionType(基本形式)

$builder              
            ->add('characteristics','collection', array(
                'label'         => 'Caracteristicas',
                 'type'         => new PromotionCharacteristicType(),
                 'allow_add'    => true,
                 'allow_delete' => true,
                 'by_reference' => false
            ))

PromotionCharacteristicType

 $builder
            ->add('name',NULL, array('label'  => 'Nome'))
            ->add('options', 'collection', array(
                'type' => new PromotionCharacteristicOptionType(),
                'allow_add' => true,
                'allow_delete' => true,      
                'prototype' => true,
                'by_reference' => false,
            ))                       
        ;

PromotionCharacteristicOptionType

 $builder
            ->add('name',NULL, array('label'  => 'Nome')) 
        ;

最初のレベルのプロトタイプは正常に動作します。

36
brpaz

フォームとプロトタイプ

異なるコレクションの2つのプロトタイプを保持する必要があります。 symfonyはそれらをdivタグのdata-prototype属性に格納することを提案し、コレクションをラップします。あなたの状況では、それは非常に非効率的です。だからあなたはそれを空のdivのどこかに手動でレンダリングすることができます

キャラクターフォームの例

class CharacterType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('opts', 'collection', array(
            'type' => new OptionType(),
            'allow_add' => true,
            'allow_delete' => true,
            'prototype' => true,
            'prototype_name' => '__opt_prot__'
        ));
        $builder->add('char_desc', 'text');
    }

    public function getName()
    {
        return 'char';
    }
}

次に、文字コレクションを含むフォームを作成します

$form = $this->createFormBuilder()
    ->add('chars', 'collection', array(
        'type' => new CharacterType(),
        'allow_add' => true,
        'allow_delete' => true,
        'prototype_name' => '__char_prot__'
    ))
    ->getForm();

    # example data
    $form->setData(
        array(
            'chars' => array(
                array('options' => array(), 'char_desc' => 1),
                array('options' => array(), 'char_desc' => 2),
            ),
        )
    );

プロトタイプを取得します

<div
    id="prots"
    data-prototype-opt="{{ form_widget(form.chars.vars.prototype.children['opts'].vars.prototype) | e }}"
    data-prototype-char="{{ form_widget(form.chars.vars.prototype) | e }}"
>
</div>

そして、このようにコレクションをレンダリングします またはcollection_widgetブロックをオーバーライドします

{% for char in form.chars %}
    {{ form_row(char.char_desc) }}
    <label for="">opts</label>
    {% for opt in char.opts %}
        {{ form_row(opt.text) }}
    {% endfor %}
{% endfor %}

それを保存する方法

可能であれば、nosqlデータベースを使用してください。または、関係データベースに対して [〜#〜] eav [〜#〜] モデルを使用します。しかし、オプションを検索したり、並べ替えたりする必要がない場合は、シリアル化された配列をデータベースに保存し、doctrine type array

30
Alexey B.

Alexey B。 の答えに追加すると、通常、コレクションのプロトタイプにアクセスできるようにするためにprototype.children['opts']を使用する必要はないようです。次のようにprototype.<collection_name>を使用します。

<div
    id="prots"
    data-prototype-opt="{{ form_widget(form.chars.vars.prototype.opts.vars.prototype) | e }}"
    data-prototype-char="{{ form_widget(form.chars.vars.prototype) | e }}"
>
</div>
1
kerdany