I submit a form from a form class to a modal, and then I perform various actions depending on which button was clicked. The purpose of the form is to edit the object.
When I show the form in modal, it will not process it no matter which button I click, however, when I render the form in a new tab, all the actions are performed correctly.
Oddly enough, although in my code right now the redirection that returns the user to the full list of resources is disabled, the page still refreshes when I click the mod button.
Decision:
I needed to manually add the form action to the form in modal mode so that it invoked the correct controller action for processing. There was not much discussion to achieve this solution, so for the convenience of others, we are here:
{{ form_start(form, {'action': path('sfi_teacher_manage_resource', { 'id': resource.id, 'action': user_action })}) }}
My form class:
<?php namespace SFI\MainBundle\Form\Type; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class ManageResourceType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('name', 'text', array( 'required' => true, 'attr' => array( 'class' => 'form-control', 'placeholder' => 'Resource name', ), )) ->add('type', 'choice', array( 'required' => true, 'empty_value' => 'Choose a type', 'choices' => array('w' => 'Website', 'v' => 'Video', 'a' => 'Audio'), 'attr' => array( 'class' => 'form-control', ), )) ->add('link', 'text', array( 'required' => true, 'attr' => array( 'class' => 'form-control', 'placeholder' => 'Add a link', ), )) ->add('description', 'textarea', array( 'required' => true, 'attr' => array( 'class' => 'textarea', 'style' => 'width: 100%; height: 200px; font-size: 14px; line-height: 18px; border: 1px solid #dddddd; padding: 10px;', 'placeholder' => 'Write a description...', ), )) ->add('save', 'submit', array( 'attr' => array( 'class' => 'btn btn-success', ), )) ->add('remove', 'submit', array( 'attr' => array( 'class' => 'btn btn-danger', ), )); } public function getName() { return 'modifyResource'; } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'SFI\MainBundle\Entity\Resource', )); } }
My route for this action:
sfi_teacher_manage_resource: path: /teacher/resource/manage/{action}/{id} defaults: { _controller: SFIMainBundle:Teacher:manageResource }
My controller action:
public function manageResourceAction($id, $action, Request $manage_request) { $logger = $this->get('logger'); $em = $this->getDoctrine()->getManager(); $managedResource = $em->getRepository('SFIMainBundle:Resource')->find($id); $logger->info('Started the manage action'); $manageResourceForm = $this->createForm(new ManageResourceType(), $managedResource); $logger->info('Loaded managedResource into FormType.'); $manageResourceForm->handleRequest($manage_request); if ($manageResourceForm->isValid()) { $logger->info('Form was valid.'); if ($manageResourceForm->get('save')->isClicked()) { $logger->info('Save was clicked, editing resource.'); $managedResource->setStatus("1"); $logger->info('Status set to approved.'); $em->persist($managedResource); $logger->info('Resource was persisted.'); } elseif ($manageResourceForm->get('remove')->isClicked()) { $logger->info('Remove / Decline was clicked'); $em->remove($managedResource); $logger->info('Resource removed.'); } $em->flush(); $logger->info('Flushing...'); $logger->info("Redirecting to teacher resources...");
As you can see, I had to bake in some console sheet to find out at what point the action stops working.
If I open the form as a new tab, everything will be fine, but not modal. I was suggested that some JavaScript might interfere with the submit buttons to work correctly, but I have no idea where to start debugging.
If you need more information, please let me know!
EDIT 1: As requested, I include how I define and create modal.
On my resources.html.twig, where the list of resources is loaded, I have several such links for each object:
{% if r.status == "0" %} <a href="{{ path('sfi_teacher_manage_resource', { 'id': r.id, 'action': 'review' }) }}" data-target="#manageResource" data-toggle="modal" class="btn btn-info bold" id="review"><i class="fa fa-fw fa-check-circle"></i>Review</a> {% elseif r.status == "1" %} <a href="{{ path('sfi_teacher_manage_resource', { 'id': r.id, 'action': 'edit' }) }}" data-target="#manageResource" data-toggle="modal" class="btn btn-info" id="edit"><i class="fa fa-fw fa-edit"></i>Edit</a> {% endif %}
The modal form itself is pre-built in the same template as Symfony, so when working with Bootstrap mods (I used to use un SF modals, and this is the only way I can think of getting them to work when loading data into them or forms):
<div class="modal fade" id="manageResource" tabindex="-1" role="dialog" aria-labelledby="Manage resource" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> Loading... </div> </div> </div>
modal-content is replaced with the contents of manageResources.html.twig as soon as the object is retrieved and loaded into the form:
{{ form_start(form) }} <div class="modal-header"> <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> <h4 class="modal-title" id="myModalLabel">Manage resource</h4> </div> <div class="modal-body"> {{ form_errors(form) }} <div class="form-group"> {{ form_errors(form.name) }} {{ form_widget(form.name) }} </div> <div class="form-group"> {{ form_errors(form.type) }} {{ form_widget(form.type) }} </div> <div class="form-group"> {{ form_errors(form.link) }} {{ form_widget(form.link) }} </div> {{ form_errors(form.description) }} {{ form_widget(form.description) }} </div> <div class="modal-footer"> <div class="pull-left"> {% if user_action == "review" %} {{ form_widget(form.save, { 'label': 'Approve' }) }} {{ form_widget(form.remove, { 'label': 'Decline' }) }} {% elseif user_action == "edit" %} {{ form_widget(form.save, { 'label': 'Save' }) }} {{ form_widget(form.remove, { 'label': 'Remove' }) }} {% endif %} </div> <div class="pull-right"> <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> </div> </div> {{ form_end(form) }}
As for all the code that is involved in this operation.