15

I have a Team to which I would like to add players (objects of Player). I've set up the form "type" classes correctly. Here's the relevant part of my view:

{% for index, player in form.players %}
    <div id="template" data-prototype="{{ form_widget(form.players.get('prototype')) | e }}">
        <span class="title">{{ index }}</span>
        {{ form_row(player.name) }}
    </div>
{% endfor %}

My problem is that data-prototype attribute doesn't include the span tag; it only contains the output of {{ form_row(player.name) }}. Is there a way to include the whole content of div#template in the data-prototype attribute?

3
  • I'm thinking of using a different form theme for form.players.get('prototype'). I'll update the post if it works. Commented Dec 14, 2011 at 19:43
  • that would be the way to go about it afaik Commented Dec 15, 2011 at 13:57
  • How did you resolve your problem here? The more general question here is, how to customize prototype? Can anyone help with that? I haven't found any consclusive information on that topic. Commented Jan 18, 2012 at 20:56

1 Answer 1

32

This was bugging me too. I customized a field type and even made simple form types with a reduced fieldset (for more complex objects), but it just didn't feel right. I've come up with a solution that should do the trick :)

First - I think your <div id="team" data-prototype="..."> should be outside your loop.

Next, your prototype is just a form view object, so if you pass it to a template you can render fields by hand and customize the output. Note: autoescape has no effect on included content, so use 'filter escape'.

<div id="playerFields" data-prototype="{% filter escape %}{% include 'AcmeTeamBundle:Team:prototypePlayer.html.twig' with {'form': form.players.get('prototype')} %}{% endfilter %}">

Then in your prototypePlayer.html.twig, just render each field as you normally would in a form view.

<div>
    <span class="title">{{ form_label(form.name) }}</span>
    {{ form_row(form.name) }}
    <span class="age">{{ form_label(form.age) }}</span>
    {{ form_row(form.age) }}
    {# render whatever else you like from your Form/PlayerType class... #}
<div>

My template has a different data structure to your question, but it should help :)

Cheers,

Chris


Deprecation Warning:

As of Symfony 2.1, .get() is deprecated and the above will not work. Replace form.players.get('prototype') with form.players.vars.prototype to fix this in later versions of Symfony.

Sign up to request clarification or add additional context in comments.

6 Comments

I came across your solution lxion, but it seems it does not use the prototype template when rendering the form once data has been submitted and you view the same form on the next page.
@Dean, Remember that the "prototype" only serves as a template for adding new collection items on the client side. Rendering existing collection items is done server-side and is not related to the prototype. This is also valid when repopulating after a failed validation. Just render all existing collection items with your prototype template like so: {% for player in form.players %} {% include 'AcmeTeamBundle:Team:prototypePlayer.html.twig' with {form: player.vars.form} %} {% endfor %}
Can't for the life of me get this to work. I think I've tried every possible combination now, and tried about 4 different SO post's but still no avail. If this still valid for Symfony2.5?
@Doug try setting by_reference to false
A really big thanks to @PhilippRieber, I've stumble a lot before finding this here!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.