何十年も前から、Symfony 2とフォームの問題をブロックしています。
Webサイトエンティティのフォームを取得しました。 「Websites」はWebサイトのエンティティのコレクションであり、各Webサイトには「type」と「url」の2つの属性が含まれています。
データベースに複数のWebサイトを追加する場合は、「別のWebサイトを追加」リンクをクリックして、別のWebサイト行をフォームに追加します。したがって、送信ボタンをクリックすると、1つまたはX個のWebサイトを同時に追加できます。
行を追加するこのプロセスでは、Webサイトのサブフォームを生成できるdata-prototype属性を使用します。
問題は、フォームをカスタマイズして優れたグラフィックレンダリングを実現することです...
<div class="informations_widget">{{ form_widget(website.type.code) }}</div>
<div class="informations_error">{{ form_errors(website.type) }}</div>
<div class="informations_widget">{{ form_widget(website.url) }}</div>
<div class="informations_error">{{ form_errors(website.url) }}</div>
ただし、データプロトタイプは、HTMLおよびCSSタグとプロパティを使用して、このカスタマイズを考慮しません。 Symfonyのレンダリングを維持します。
<div>
<label class=" required">$$name$$</label>
<div id="jobcast_profilebundle_websitestype_websites_$$name$$">
<div>
<label class=" required">Type</label>
<div id="jobcast_profilebundle_websitestype_websites_$$name$$_type">
<div>
<label for="jobcast_profilebundle_websitestype_websites_$$name$$_type_code" class=" required">label</label>
<select id="jobcast_profilebundle_websitestype_websites_$$name$$_type_code" name="jobcast_profilebundle_websitestype[websites][$$name$$][type][code]" required="required">
<option value="WEB-OTHER">Autre</option>
<option value="WEB-RSS">Flux RSS</option>
...
</select>
</div>
</div>
</div>
<div>
<label for="jobcast_profilebundle_websitestype_websites_$$name$$_url" class=" required">Adresse</label>
<input type="url" id="jobcast_profilebundle_websitestype_websites_$$name$$_url" name="jobcast_profilebundle_websitestype[websites][$$name$$][url]" required="required" value="" />
</div>
</div>
</div>
誰もがそのハックをする考えを持っていますか?
少し古いですが、ここに致命的な単純な解決策があります。
アイデアは、Twigテンプレートを使用してコレクションアイテムをレンダリングすることです。したがって、data-prototype="..."
タグ。まるで普通の普通の形のように。
MainForm.html.twigで:
<div id="collectionContainer"
data-prototype="
{% filter escape %}
{{ include('MyBundle:MyViewsDirectory:prototype.html.twig', { 'form': form.myForm.vars.prototype }) }}
{% endfilter %}">
</div>
そしてMyBundle:MyViewsDirectory:prototype.html.twig:
<div>
<!-- customize as you wish -->
{{ form_label(form.field1) }}
{{ form_widget(form.field1) }}
{{ form_label(form.field2) }}
{{ form_widget(form.field2) }}
</div>
私はこの質問がかなり古いことを知っていますが、私は同じ問題を抱えていました。これを達成するためにtwig macro
を使用しています。マクロは関数のようなものであり、異なる引数でレンダリングできます。
_{% macro information_prototype(website) %}
<div class="informations_widget">{{ form_widget(website.type.code) }}</div>
<div class="informations_error">{{ form_errors(website.type) }}</div>
<div class="informations_widget">{{ form_widget(website.url) }}</div>
<div class="informations_error">{{ form_errors(website.url) }}</div>
{% endmacro %}
_
これで、必要な場所にこのマクロをレンダリングできます。 information_prototype()
はマクロの名前であり、任意の名前を付けることができます。マクロを使用して特定のアイテムとプロトタイプを同じ方法でレンダリングする場合は、次のようにします。
_<div class="collection" data-prototype="{{ _self.information_prototype(form.websites.vars.prototype)|e }}">
{% for website in form.websites %}
{{ _self.information_prototype(website) }}
{% endfor %}
<button class="add-collection">Add Information</button>
</div>
_
_form.websites.vars.prototype
_は、指定した_prototype_name
_を持つフォームのプロトタイプデータを保持します。同じテンプレートでマクロを使用する場合は、__self.+macroname
_を使用します。
Twigドキュメント でマクロの詳細を確認できます。
おそらくあなたはそれ以来知っているでしょうが、ここに他の人のための解決策があります。
新しいテンプレートを作成し、このコードをコピーして貼り付けます: https://Gist.github.com/1294186
次に、カスタマイズするフォームを含むテンプレートで、これを実行してフォームに適用します。
{% form_theme form 'YourBundle:Deal:Theme/_field-prototype.html.twig' %}
回答が非常に遅いことは知っていますが、訪問者にとっては役に立つかもしれません。
テーマファイルでは、1つのブロックを使用して、次のようにWebサイトウィジェットのすべてのコレクションエントリをレンダリングできます。
{% block _jobcast_profilebundle_websitestype_websites_entry_widget %}
<div class="informations_widget">{{ form_widget(form.type.code) }}</div>
<div class="informations_error">{{ form_errors(form.type) }}</div>
<div class="informations_widget">{{ form_widget(form.url) }}</div>
<div class="informations_error">{{ form_errors(form.url) }}</div>
{% endblock %}
また、次のようにコレクションウィジェット行のテーマブロックを作成します。
{% block _quiz_question_answers_row %}
{% if prototype is defined %}
{%- set attr = attr | merge({'data-prototype': form_row(prototype) }) -%}
{% endif %}
{{ form_errors(form) }}
{% for child in form %}
{{ form_row(child) }}
{% endfor %}
{% endblock %}
これで、プロトタイプとレンダリングされたコレクションのエントリは同じになります。
最近、同様の問題に遭遇しました。 htmlで明示的に設定せずにコレクションプロトタイプをオーバーライドする方法は次のとおりです。
{% set customPrototype %}
{% filter escape %}
{% include 'AcmeBundle:Controller:customCollectionPrototype.html.twig' with { 'form': form.collection.vars.prototype } %}
{% endfilter %}
{% endset %}
{{ form_label(form.collection) }}
{{ form_widget(form.collection, { 'attr': { 'data-prototype': customPrototype } }) }}
カスタムの小枝で何でもできます。例えば:
<div data-form-collection="item" data-form-collection-index="__name__" class="collection-item">
<div class="collection-box col-sm-10 col-sm-offset-2 padding-top-20">
<div class="row form-horizontal form-group">
<div class="col-sm-4">
{{ form_label(form.field0) }}
{{ form_widget(form.field0) }}
</div>
<div class="col-sm-3">
{{ form_label(form.field1) }}
{{ form_widget(form.field1) }}
</div>
<label class="col-sm-3 control-label text-right">
<button data-form-collection="delete" class="btn btn-danger">
<i class="fa fa-times collection-button-remove"></i>{{ 'form.collection.delete'|trans }}
</button>
</label>
</div>
</div>
特定の場所でのみ行う必要があり、すべてのコレクションに適用可能なグローバルオーバーライドが必要ない場合に役立ちます。
似たような問題がありました。あなたのケースのためにこれを微調整する必要があるかもしれませんが、誰かがそれを役に立つと思うかもしれません。
カスタムテンプレート「テーマ」を保持する新しいテンプレートファイルを作成します
./src/Company/TestBundle/Resources/views/Forms/fields.html.twig
通常、使用できます form_row フィールドのラベル、エラー、ウィジェットを表示する関数。しかし、私の場合は、ウィジェットを表示したかっただけです。あなたが言うように、データプロトタイプ機能を使用するとラベルも表示されるので、新しいfields.html.twigで、フィールドの外観に合わせてカスタムコードを入力します。
{% block form_row %}
{% spaceless %}
{{ form_widget(form) }}
{% endspaceless %}
{% endblock form_row %}
コンテナdivとラベルとエラーを削除し、ウィジェットを残しました。
次に、フォームを表示するtwigファイルで、{%extends ...%}の後にこれを追加します
{% form_theme form 'CompanyTestBundle:Form:fields.html.twig' %}
そして今、form_widget(form.yourVariable.var.prototype)はフィールドのみをレンダリングし、それ以外は何もレンダリングしません。
アプリケーション全体のフォームテーマがプロトタイプに適用されます。 アプリケーション全体のカスタマイズの作成 を参照してください
システム全体でテンプレートを定義する必要がない場合は、twigテンプレートにテンプレートを設定し、twigを使用してください。
{# using the profiler, you can find the block widget tested by twig #}
{% block my_block_widget %}
<div >
<p>My template for collection</p>
<div >
{{ form_row(form.field1)}}
</div>
<div>
{{ form_row(form.field2)}}
</div>
</div>
{% endblock %}
{% form_theme form.my_collection _self %}
<button data-form-prototype="{{ form_widget(form.my_collection.vars.prototype) )|e }}" >Add a new entry</button>
異なる既存のコレクションアイテムVSプロトタイプをカスタマイズするには、次のようにcollection_widgetをオーバーライドできます。
{%- block collection_widget -%}
{% if prototype is defined %}
{%- set attr = attr|merge({'data-prototype': form_row(prototype, {'inPrototype': true} ) }) -%}
{% endif %}
{{- block('form_widget') -}}
{%- endblock collection_widget -%}
そして、カスタムエントリで:
{% block _myCollection_entry_row %}
{% if(inPrototype is defined) %}
{# Something special only for prototype here #}
{% endif %}
{% endblock %}