0

I have a simple FormType attached to an entity called media wich I rendered in my view. I have a newAction that lets me create my object, and a editAction that lets me edit it with my same form in my controller. However I don't want some field appears in my editview` as I already entered them when I created it.

But even though I use form_row to specifically render my form line by line, when I add the form_end at the end, it renders all my fields, even the ones I didn't call.

My FormType

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('name', FileType::class, array(
            'data_class'          => null,
            'label'               => "Add an image"
        ))
        ->add('context', ChoiceType::class, array(
            'label'               => 'image section',
            'choices' => array(
                'header' => 'header',
                'middle' => 'middle',
            )
        ))
        ->add('save', SubmitType::class, array(
            'label'               => "Add"
        ));
}

My view

{{ form_start(editForm) }}
{{ form_row(editForm.name) }}
{{ form_row(editForm.save) }}
{{ form_end(editForm) }}

But even if I use the form rows, it actually shows my context field in the view, which I didn't call. So I tried some hack to get around it.

this one worked but when I click on submit form, it shows me an error that context field cannot be null, so this doesn't do the trick

{% do editForm.context.setRendered %}

And I found a way to do it with jQuery to hide the form like this

<script>
        $(document).ready(function () {
            $("#media_context").parent().hide();
        });
    </script>

the jQuery works and hide my row in my form. But I was wondering if I could do it without using jQuery and be able to render only specific field of my form in my view?

chicken burger
  • 774
  • 2
  • 12
  • 32
  • You have to add `'required' => false` to `context` field in form builder if you want submit form without this field. – malcolm Mar 19 '17 at 10:43
  • hi @malcolm, thanks for answering but your proposition doesn't work, the field appears even when I add the `required` :( – chicken burger Mar 19 '17 at 10:53
  • Because `form_end` add all missing fields. My comment was about the error "field cannot be null". You can now use `{% do editForm.context.setRendered %}`. – malcolm Mar 19 '17 at 10:56
  • Ha I see ! so how can I render a form with specific field without rendering some of them like in my question? How can I do that? I still need the `form_start` and `form_end` right? but if its rendering all fields automatically, what is the point to have a `form_row` then? By the way your solution still doesn't work, I have this error `SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'context' cannot be null` even after added `required => false` – chicken burger Mar 19 '17 at 10:59
  • Also consider: "Best Practice: Add buttons in the templates, not in the form classes or the controllers." http://symfony.com/doc/current/best_practices/forms.html#form-button-configuration – malcolm Mar 19 '17 at 11:01
  • @malcolm thanks for the link, I will check that for my submit button. rather having in the form I will add it to my view. But I still have my problem about generating specific field from the form :( – chicken burger Mar 19 '17 at 11:03
  • You have to set default value for you entity field dn allow null values http://stackoverflow.com/a/9986331/3675759 – malcolm Mar 19 '17 at 11:03
  • The point to have `form_row` is that you can rearrange or style with HTML your form field, and later `form_end` displays all the rest fields. You can ommit `form_end` and display the crsf token and submit widget like the rest of fields. – malcolm Mar 19 '17 at 11:07
  • I tried adding the value `null` to my entity. it worked but didn't display my image properly. I guess there is some trouble with that. so I can do that by omitting writing form_end that is all? what about the crsf token? should I add it that too? – chicken burger Mar 19 '17 at 11:11
  • I didn't thought that this was complicated to solve :/..... nobody have a clue on how to not show a specific field from a form? I didn't get the crsf token – chicken burger Mar 19 '17 at 11:32
  • Cannot understand you, you need that field in your entity, but you don't want that field to appear inside form? – malcolm Mar 19 '17 at 11:34
  • @malcolm yes. Actually I have a controller that calls this form to be able to `create` and `edit` so when I want to create my form i want to choose the `context` but when I edit it, i should not see the `context` as it has already been given. That is why I try to hide this field when I edit, but keep it when I create a new entry – chicken burger Mar 19 '17 at 11:36
  • Why go through all this hassle? Just make two forms and be done with it. – Cerad Mar 19 '17 at 13:41
  • @cerad I never knew I could make two form for one entity. I don't have all knowledge – chicken burger Mar 19 '17 at 13:51
  • Can't begin to tell you how many times I have banged my ahead against a wall trying to solve a "complex" problem only to have a simple solution staring at me right in the face. – Cerad Mar 19 '17 at 13:58
  • @cera haha yeah, it feels exactly like that.I feel you – chicken burger Mar 19 '17 at 14:00

3 Answers3

5

In Symfony 2, you could remove some fields from the builder when editing your entity. Your edit form must extends your create form in Symfony 2.

I think you can do the same in Symfony 3, try something like :

class EditType extends CreateType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);

        $builder
            ->remove('context') //remove the fields that no longer needed
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        /...
    }
}

You don't need to change CreateType

class Createtype extends AbstractType
{
  public function buildForm(FormBuilderInterface $builder, array $options)
  {
    $builder
        ->add('name', FileType::class, array(
            'data_class'          => null,
            'label'               => "Add an image"
        ))
        ->add('context', ChoiceType::class, array(
            'label'               => 'image section',
            'choices' => array(
                'header' => 'header',
                'middle' => 'middle',
            )
        ))
        ->add('save', SubmitType::class, array(
            'label'               => "Add"
        ));
  }
}
mickdev
  • 2,765
  • 11
  • 15
  • Hi @mickedv if i understand correctly your solution. It means that in my AppBundle/Form I need to have a folder called `MediaType` for my media entity. In this folder I have `CreateType` and `EditType` ? I currently only have only one form just like in my question. So I need to have 2 forms? one for creating and one for editing? – chicken burger Mar 19 '17 at 12:44
  • Hi @crisscross, instead of creating a workaround with javascript `$("#media_context").parent().hide();`, I will recommend creating two forms. It's clean and if you want to remove another form in the future it will be very simple. Your code will be more maintainable this way – mickdev Mar 19 '17 at 12:50
  • @mickedv what you propose me sounds like a great solution! :) I will try it right away! but your answer is incomplete. You see my formType in my question right? it is the one I use currently. so what should I put in createType and EditType then? can you update your answer because I still don't know where to put the `remove` option – chicken burger Mar 19 '17 at 12:52
  • Should I put them in a folder named after my entity? – chicken burger Mar 19 '17 at 13:16
  • In Symfony 2, entity is in `/entity` folder and forms in `/form` folder. I don't know about Symfony 3 but just follow the convention. Where did you put your formtypes ? – mickdev Mar 19 '17 at 13:19
  • I putted my FormTypes in the Form folder in the AppBundle.I guess its pretty similar to symfony 2 (im refactoring my code to suit your answer at this moment) – chicken burger Mar 19 '17 at 13:22
  • I have a new error `Type error: Argument 1 passed to AppBundle\Services\FileUploader::upload() must be an instance of Symfony\Component\HttpFoundation\File\UploadedFile, null given, called in /var/www/html/FoodAndYou_V2/src/AdminBundle/Controller/MediaController.php on line 61` he doesn't like my double form. I wonder what is this new issue :/ – chicken burger Mar 19 '17 at 13:30
  • Do you attribute the correct form to the correct action ? createAction: `$form =$this->createForm(new CreateType(), $entity);` and EditAction: `$form = $this->createForm(new EditType(), $entity);`. Also, line 61 is in create or edit action ? – mickdev Mar 19 '17 at 13:40
  • I have this for createAction `$form = $this->createForm(MediaType\CreateType::class, $media);` and this for editAction `$editForm = $this->createForm(MediaType\EditType::class, $media)` – chicken burger Mar 19 '17 at 13:53
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/138459/discussion-between-mickdev-and-criss-cross). – mickdev Mar 19 '17 at 14:10
3

From the symfony docs:

This helper (form_end) also outputs form_rest() unless you set render_rest to false.

form_rest(view, variables)

This renders all fields that have not yet been rendered for the given form.

{# don't render unrendered fields #}
{{ form_end(form, {'render_rest': false}) }}
Chris
  • 799
  • 6
  • 15
1

Try this

{{ form_start(editForm) }}
{{ form_row(editForm.name) }}
{{ form_row(editForm.save) }}
{{ form_end(editForm, {'render_rest': false}) }}
Azam Alvi
  • 6,918
  • 8
  • 62
  • 89