I'm new to symfony and I'm trying to learn but I'm stuck at the moment :
I'm trying to create a form with input already filled, let me explain :
I've got a Session table, linked with an antibiotic (when I create a session, I choose an Antibiotic), Antibiotic table is linked to Result table.
Like this : Tables
What I'm trying to do, is when I click on Valid Result on Result list page, it creates a form of a new result with antibiotic input already filled (because a Session has one Antibiotic)
This is what i've got now (where 6 is the Antibiotic ID from the Session) :
Add Results page
I've tried to look on how edit pages works with no results.
Thanks
/**
* #Route("/session/resultat/{id}", name="addResultat")
*/
public function voirAction($id, Request $request){
//Find the Session object
$em=$this->getDoctrine()->getManager();
$session=$em->getRepository("AppBundle:Session")
->find($id);
if ($session==null)
{
throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException("Ouste !");
}
$resultat = new Resultat();
$form = $this->createForm('AppBundle\Form\ResultatType', $resultat);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($resultat);
$em->flush();
return $this->redirectToRoute('resultat_show', array('id' => $resultat->getId()));
}
return $this->render('resultat/addresultats.html.twig', array(
'resultat' => $resultat,
'session' => $session,
'form' => $form->createView(),
));
}
I got it to work finally thanks to ccKep :
Just set my object before creating the form like this :
So after I initialised my new "resultat", i can set his "antibiotique" with setter method and I get it from the $session with the getter method
$resultat->setAntibiotique($session->getAntibiotique());
Related
I have an index page which contains a simple form; if the form validation fails the index page is reloaded with errors if not then the action related to the page forwards the request to another action related to page success. The success page uses the form submitted to create a list from DB. Once we are on success page we have another form similar to the first one which the user can use to modify the list on the page. Both forms have same fields.
index page action:
class DefaultController extends Controller {
/**
* #Route("/", name="homepage")
*/
public function indexAction(Request $request) {
$event = new Event();
$form = $this->createForm(EventForm::class, $event);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
// Do some minor modification to the form data
$event->setDate($party->getDate()->modify('+12 hours'));
$cityName = strtolower($event->getPlace()['city']);
// We know the form data is valid, forward it to the action which will use it to query DB
return $this->forward('AppBundle:Frontend/Default:eventsList', array('request' => $request));
}
// If validation fails, reload the index page with the errors
return $this->render('default/frontend/index.html.twig', array('form' => $form->createView()));
}
success page action (where the form data gets forwarded)
/**
* #Route("/success", name="eventList")
*/
public function eventsListAction(Request $request) {
$event = new Party();
// Create a form in the second page and set its action to be the first page, otherwise form submition triggers the FIRST action related to page index and not the one related to page success
$form = $this->createForm(EventForm::class, $event, array('action' => $this->generateUrl('eventList')));
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$event->setPlace($form["place"]->getData());
$event->setTitle($form["title"]->getData());
$repository = $this->getDoctrine()
->getRepository('AppBundle:Event');
// ....
// Create a list of events using the data from DB
// ....
return $this->render('default/frontend/success.html.twig',
array('events' => $events, 'form' => $form->createView())
);
}
return $this->render('default/frontend/success.html.twig', array('form' => $form->createView()));
}
Although the above implementation "works" I have a couple of issues:
When I submit the first form the url stays the same, that of the first page like:
[HOST]/app_dev.php?place=London&Date=......
But if I submit the second form the URL is correctly:
[HOST]/app_dev.php/success?place=London&date=.....
The implementation feels hacky to me, is there a cleaner way to achieve this?
When the form is submitted, then it's porcessed with the same controller and action. You have to process the submited data and then redirect to success page.
So in your example:
if($form->isSubmitted() && $form->isValid()) {
...
...
return $this->redirectToRoute('eventList');
}
And if you need to transfer posted data from one "page" to another, then you have to store it in session $this->get('session')->set('name', val); and then retrieve data from session in eventList action by $this->get('session')->get('name');
More info how to handle sessions in Symfony: https://symfony.com/doc/current/controller.html#the-request-object-as-a-controller-argument
I have a page index.html.twig which contains a Form this form when submitted, get validated and the result is shown in a page success.html.twig. Now I have a new requirement where the page success.html.twig itself contains a Form which should contain the values which were passed by the form from index.html.twig and if the user wants the new form should also allow the user to do search directly from success.twig.html. The requirement is inspired by hostel world.
Questions:
Is there a design pattern which I could use to implement a solution
My current thinking is to create a new Action for success.html.twig and submit the form to thatAction instead of rendering success.html.twig from index.html.twig's Action. Is it correct? How can I implement it?
Code (Partial):
/**
* #Route("/", name="homepage")
*/
public function indexAction(Request $request)
{
$event = new Event();
$form = $this->createForm(MyForm::class, $event);
$form->handleRequest($request);
if($form->isSubmitted() && $form->isValid()) {
$event->setPlace($form["place"]->getData());
$event->setDate($form["date"]->getData()->modify('+12 hours'));
return $this->render('default/frontend/success.html.twig',
array('events' => $events, 'cityName' => $cityName, 'cityImage' => $cityImage)
);
}
return $this->render('default/frontend/index.html.twig', array('form' => $form->createView()));
}
It makes sense to have two different actions - at least for different request types (GET, POST, etc..)
There is just one thing as advice: $form->isValid() has already an isSubmitted() check inside. So there is no need to check whether it is submitted or not.
ok, I have submitted serialized data via AJAX using JQuery into a function within my Symfony 2 (2.7.10) app.
I am now having a few issues with trying to bind that data to a new entity and save that entity.
Here is what I have done to date:
public function AJAX_SaveTestAction(Request $request) {
// $GetFormData = $request->get('Data'); <- This is a jquery serialized data
$NewData = new TestInfo(); <- this is the entity I want to save
$form = $this->createForm(new InfoType(), $NewData);
$form->handleRequest($request);
if ( $request->isMethod('POST') ) {
$form->bind( $request->get('Data') );
$em = $this->getDoctrine()->getManager();
$em->persist( $NewData ); <- not saving jquery returns 500 server error?
$em->flush();
}
die(); <- this is just here for testing, I will want to return a json message or something else!
}
All help most welcome.
Thanks.
Don't use form->handleRequest and form->bind
form->bind was the equivalent of form->handleRequest before Symfony 2.6.
If you are using Symfony 2.3 use form->bind
If you are using Symfony 2.6+ use form->handleRequest
Your Controller should look like :
public function AJAX_SaveTestAction(Request $request)
{
$NewData = new TestInfo();
$form = $this->createForm(new InfoType(), $NewData);
$form->handleRequest($request);
if($form->isSubmitted()){ // if you also want to check if your entity is valid, just replace it with "if($form->isValid()){"
$em = $this->getDoctrine()->getManager();
$em->persist( $NewData );
$em->flush();
return new Response('It works');
}
return new Response('error');
}
But your JS should send a POST request to this route (with post parameters).
May be with that :
http://api.jquery.com/jquery.post/
To bind correctly your request data to your entity using handleRequest, Symfony expects an array with your form name as key in your POSTed data.
If you did not override method getName of your form, it is defined by default by "underscoring" your Form class name. So it should be info_type here.
TL;DR: You should submit your data as ['info_type' => [ YOUR DATA... ]] instead of just [ YOUR DATA... ]
I am new at Zend2:
I have a form, and in the first stage I create a new ViewModel and return it:
return new ViewModel(array('form' => $form, 'messages' => $messages));
In the post stage when the data comes back from the browser, how can I connect this same form to a new View (which has the same elements maybe less, maybe more) or create another form and rassign it the old form's data and relate it to a new view to show?
Any help would be appreciated.
EDIT:
I tried to do the following:
$form->setAttribute('action', $this->url('auth/index/login-post.phtml'));
But still shows the old one.
When I do this:
return $this->redirect()->toRoute('auth/default', array('controller' => 'index', 'action' => 'login-post'));
I get error page: The requested controller was unable to dispatch the request.
When I get the post of the request I need to load another view, I mean how do I specify which view is connected to which form?
The forms do not themselves have any knowledge of the view. If you wish to change the view after completing the form submission; where this new view provides perhaps a different form, this is something that should be done within the controller.
A (non-working) example with a few options on how a different view could be returned.
class FooController extends AbstractActionController
{
public function getFooForm()
{
return $this->getServiceLocator()->get('Form\Foo');
}
public function getBarForm()
{
return $this->getServiceLocator()->get('Form\Bar')
}
public function fooAction()
{
$request = $this->getRequest();
$form = $this->getFooForm();
if ($request->isPost()) {
$form->setData($request->getPost());
// Is the posted form vaild
if ($form->isValid()) {
// Forms validated data
$data = $form->getData();
// Now there are a few options
// 1. Return a new view with the data
$view = new ViewModel($data);
$view->setTemplate('path/to/file');
return $view;
// OR Option 2 - Redirect
return $this->redirect()->toRoute('bar', $someRouteParams);
// Option 3 - Dispatch a new controller action
// and then return it's view model/response
// We can also pass on the posted data so the controller
// action that is dispathed will already have our POSTed data in the
// request
$request->setPost(new \Zend\Stdlib\Parameters($data));
return $this->forward()->dispatch('App\Controller\Foo', array('action' => 'bar'));
}
}
// Render default foo.phtml or use $view->setTemplate('path/to/view')
// and render the form, which will post back to itself (fooAction)
return new ViewModel(array('form' => $form));
}
public function barAction()
{
$request = $this->getRequest();
$form = $this->getBarForm();
if ($request->isPost()) {
$form->setData($request->getPost());
// ....
}
// Renders the bar.phtml view
return $this->viewModel(array('form' => $form));
}
}
From what I understand form your question, you would need to be using option 3 as the new view should populate a second form with it's already validated data.
If you are referring to something like an edit view then you just need to bind your object to the form.
$form->bind($yourObject);
http://zf2.readthedocs.org/en/latest/modules/zend.form.quick-start.html#binding-an-object
Otherwise you can make the form post to any controller action using by setting it:
$form->setAttribute('action', $this->url('contact/process'));
Maybe post what code you have and more specifics and I'm sure you will get some more detailed answers
I have a form in Symfony2 framework. On successful submission of the page it renders another twig template file and returns the values by passing the parameters in an array. But after submission, if I refresh the page, again it is submitting the form and the table entry is created. Here is the code that is executed after submission in the controller,
$this->get('session')->setFlash('info', $this->get('translator')->trans('flash.marca'));
return $this->render('NewBundle:Backend:marca.html.twig', array(
'active' => 1,
'marca' => $marca,
'data' => $dataCamp,
'dataMarca' => $this->getMarcas($admin->getId()),
'admin' => $admin,
));
I want the form to be redirected to the twig files mentioned there with the parameters and the alert message mentioned above. But I don't want the form to be submitted on page refresh.
Thanks
This worked for me:
return $this->redirectToRoute("route_name");
You should save submitted data in session and redirect user. Then you will be able to refresh page as much as you want without additional submission.
Example code - your action algorithm should be similar:
...
/**
* #Route("/add" , name="acme_app_entity_add")
*/
public function addAction()
{
$entity = new Entity();
$form = $this->createForm(new EntityType(), $entity);
$session = $this->get('session');
// Check if data already was submitted and validated
if ($session->has('submittedData')) {
$submittedData = $session->get('submittedData');
// There you can remove saved data from session or not and leave it for addition request like save entity in DB
// $session->remove('submittedData');
// There your second template
return $this->render('AcmeAppBundle:Entity:preview.html.twig', array(
'submittedData' => $submittedData
// other data which you need in this template
));
}
if ($request->isMethod('POST')) {
$form->bindRequest($request);
if ($form->isValid()) {
$this->get('session')->setFlash('success', 'Provided data is valid.');
// Data is valid so save it in session for another request
$session->set('submittedData', $form->getData()); // in this point may be you need serialize saved data, depends of your requirements
// Redirect user to this action again
return $this->redirect($this->generateUrl('acme_app_entity_add'));
} else {
// provide form errors in session storage
$this->get('session')->setFlash('error', $form->getErrorsAsString());
}
}
return $this->render('AcmeAppBundle:Entity:add.html.twig', array(
'form' => $form->createView()
));
}
Redirect to same page is preventing additional data submission. So lean of this example modify your action and you will be fine.
Also instead save data in session you can pass it through redirect request. But I think this approach is more difficult.
Save your data (session/db/wherever you want it saved)
redirect to a new action, retreiving the new data in that action, and rendering the template
this way, refreshing the new action, will only refresh the template, as the saving of your data happened in the previous action
understand ?
so basically replace your
return $this->render....
by
return $this->redirect($this->generateUrl('ROUTE_TO_NEW_ACTION')));
and in this new action, you put your
return $this->render....