72

I've started to use Symfony2 but I've some problems. I wanted to render fields by hand but it doesn't work because my field yet rendered by me is displayed with the form_rest() function too, so I have two same fields.

Here is my code :

<div>
     {{ form_errors(form.contenu) }}
     <textarea id="{{ form.contenu.vars.id }}" name="{{ form.contenu.vars.full_name }}">{{ form.contenu.vars.value }}</textarea>
</div>

And, at the form's end, I must put this :

{{ form_rest(form) }}

But it displays the "contenu" field :(

Do you have an idea of what's the problem ?

j0k
  • 22,600
  • 28
  • 79
  • 90
Ilan Coulon
  • 1,126
  • 1
  • 7
  • 14
  • Is, by any chance, your form called "form"? At which version of Symfony this solution worked for you? I'm trying to do the same but it doesn't work. – userfuser Sep 29 '13 at 15:41

4 Answers4

209

Another option is to explicitly mark the field as rendered:

{% do form.contenu.setRendered %}
Francesc Rosas
  • 5,915
  • 2
  • 30
  • 16
  • in PHP it would be setRendered(true) ?> – Tomas Dermisek Feb 11 '15 at 01:46
  • 2
    @TomasDermisek No `\Symfony\Component\Form\FormView::setRendered` has no arguments. And since there is no `setUnrendered` and `$rendered` is a private method, you can't use `{{ form_row(form.contenu) }}` later on in your code. – Stephan Vierkant Jun 24 '18 at 14:42
  • 1
    @StephanVierkant, the trick is to first do `{% set formDescription = form_row(form.description) %}` then `{{ form_rest(form) }}` and then `{{ formDescription|raw }}`. – TheFrost Apr 04 '19 at 05:55
64

Another in my opinion less hacky way to do it is this:

{{ form_widget(form._token) }} // render the CSRF Token
{{ form_end(form, {'render_rest': false}) }} // do not render anything else

It's from the official documentation (v3.0) so it's pretty much best practise i guess.

Andresch Serj
  • 35,217
  • 15
  • 59
  • 101
33

{{ form_rest(form) }} goes at the very end, after rendering each field "manually". If you are using it for the CSRF token you can always render it with:

{# Token CSRF #}
{{ form_widget(form._token) }}
gremo
  • 47,186
  • 75
  • 257
  • 421
  • 36
    very useful in combination with `{{ form_widget(form._token) }}` `{{ form_end(form, {'render_rest': false}) }}` – Barno Dec 19 '13 at 15:53
10

The situation in which you don't want to show some field suggests badly designed form. You could feed some argument(s) into it's __construct to make it conditional (say, include/exclude some fields) or you could just create separate Form classes (which is, in my opinion, a bit overkill).

I had common case few months ago when form differed when user inserted/updated records. It was something like this:

...
public function __construct($isUpdateForm){
    $this->isUpdateForm= $isUpdateForm;
}

public function buildForm(FormBuilder $builder, array $options){
    ....
    $builder->add('some_filed', 'text', ..... );

    if ( $this->isUpdateForm ){
        $builder->add(.....);
    }
    ....
}
....

If for some reasons you're not able to refactor form class you could still display unwanted fields but wrap them into <div> which has CSS display:none attribute. That way "they are still there" (and by all means are processed normally) but are not visible to user.

Hope this helps...

Jovan Perovic
  • 19,846
  • 5
  • 44
  • 85
  • Thank, but that wasn't what I want (I've found a solution, see my EDIT). I wanted to say to Symfony I've already display the field ;) – Ilan Coulon May 15 '12 at 16:11
  • Even better would be different forms for adding or updating an entity. My experience is that you'll add `$isUpdateForm` to your constructor, later on you'll add `$isAdmin` and `$isOwner`, etc. etc. – Stephan Vierkant Jun 24 '18 at 14:46
  • @StephanVierkant while I had no such case so far, that is certainly a possibility. But then, with individual forms, dev should pay attention to minimize duplication (or have none at all). Nothing is worse than fixing a bug in one place, just to uncover that there is a same snippet that you really haven’t been aware of at all... :-) – Jovan Perovic Jun 24 '18 at 14:53