Symfony Forms - Datatime Add +30minutes - forms

When I set beginAt(DateTime) in Forms I would like set the same date in the "endAt" but +30 minutes. I have no clu how to do this :(
The first code is the part Form in my project and the second code is function "new Appointment" to add appointment.
$builder
->add('title', TextType::class, ['label'=>'Tytuł'])
->add('description', TextType::class, ['label'=>'Treść'])
->add('beginAt')
->add('endAt')
;
public function new(Request $request, $id, TokenStorageInterface $tokenStorage): Response
{
$currentUser = $tokenStorage->getToken()
->getUser();
$username = $currentUser->getUsername();
$appointment = new Appointments();
$appointment->setDoctor($id);
$appointment->setUsername($username);
$form = $this->createForm(AppointmentsType::class, $appointment);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($appointment);
$em->flush();
return $this->redirectToRoute('przychodnia_index');
}
return $this->render('appointments/new.html.twig', [
'appointment' => $appointment,
'form' => $form->createView(),
]);
}

Try to use Symfony Form Events to update endAt field on submit for example and use some ajax to submit your form dynamically. There is a great tutorial here (in French sorry) https://www.grafikart.fr/tutoriels/champs-imbriques-888

Related

How to send flash message to form error field (Symfony)

This is my registration form code:
public function register(Request $request, UserPasswordEncoderInterface $passwordEncoder)
{
$user = new User();
$form = $this->createForm(RegisterType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$password = $passwordEncoder->encodePassword($user, $user->getPlainPassword());
$user->setPassword($password);
$user->setPlan('1');
$datetime = new \DateTime();
$datetime->modify('+30 day');
$user->setExpiration($datetime);
$user->setActive('0');
$entityManager = $this->getDoctrine()->getManager();
$entityManager->persist($user);
$entityManager->flush();
$this->addFlash('success', 'Your account has been created. Check your inbox for verification e-mail.');
}
return $this->render('home/register.html.twig', array(
'form' => $form->createView(),
));
}
At the end of saving user into database there's set Flash message. Is there any way of showing that message through form error field?
No you cannot add a flash message to a form's errors. The only way to manipulate the errors of a form through it's class API is the public function addError(FormError $error) but as you can see it's only accepts arguments of type FormError not strings.

Symfony3 : multi-steps form and flush after forward

I have a form to add a new prescriber in my database. The first step consists in informing the various informations about the prescriber.
Then, I check if there are similar prescribers before adding it (2nd step with a 2nd form) and if there are, I ask the user to confirm.
In short, I have a 1-step form or a 2-steps form, depending on duplicates.
I tried with CraueFormFlowBundle but I don't know how to implement my conditional second step. My tests were inconclusive. So I decided to use forward method in my controller, and I like it !
But, I can't manage to flush my prescriber at the end of the 2nd step (after forwarding), I have this error : Unable to guess how to get a Doctrine instance from the request information for parameter "prescriber".
addAction (= step 1)
/**
* Add a new prescriber
*
* #Route("/prescribers/add", name="prescriber_add")
*/
public function addAction(Request $request) {
$em = $this->getDoctrine()->getManager();
$rp = $em->getRepository('AppBundle:Prescriber');
$p = new Prescriber();
// build the form
$form = $this->createForm(AddPrescriberType::class, $p);
// handle the submit
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
# search if a prescriber already exists
$qb = $rp->createQueryBuilder('p');
$qb->where($qb->expr()->eq('p.rpps', ':rpps'))
->orWhere($qb->expr()->andX(
$qb->expr()->like('p.lastname', ':name'),
$qb->expr()->like('p.firstname', ':firstname')
))
->setParameter('rpps', $p->getRpps())
->setParameter('name', '%'.$p->getLastname().'%')
->setParameter('firstname', '%'.$p->getFirstname().'%');
$duplicates = $qb->getQuery()->getArrayResult();
# there are duplicates
if (!empty($duplicates)) {
$em->persist($p);
// confirm the addition of the new prescriber
$params = array('prescriber' => $p, 'duplicates' => $duplicates);
$query = $request->query->all();
return $this->forward('AppBundle:Prescriber:addConfirm', $params, $query);
} else {
$em->persist($p); # save the prescriber
$em->flush(); # update database
$this->addFlash('p_success', 'The prescriber has been created successfully');
return $this->redirectToRoute('prescriber');
}
}
// show form
return $this->render('prescribers/form-step1.html.twig', array(
'form' => $form->createView()
));
}
addConfirmAction (= step 2)
/**
* Confirm addition of a new prescriber
*
* #Route("/prescribers/add/confirm", name="prescriber_add_confirm")
*/
public function addConfirmAction(Prescriber $prescriber, $duplicates, Request $request) {
$em = $this->getDoctrine()->getManager();
$form = $this->createFormBuilder()->getForm();
if ($form->handleRequest($request)->isValid()) {
$em->persist($prescriber);
$em->flush();
$this->addFlash('p_success', 'Prescriber has been created successfully');
return $this->redirectToRoute('prescriber');
}
// show confirm page
return $this->render('prescribers/form-step2.html.twig', array(
'h1_title' => 'Ajouter un nouveau prescripteur',
'form' => $form->createView(),
'p' => $prescriber,
'duplicates'=> $duplicates
));
}
I think the problem comes from the fact that I have 2 forms submissions...
I found a solution by using the session.
(I know it's not a perfect way but I didn't find other one)
For Symfony 3.3.*
use Symfony\Component\HttpFoundation\Session\SessionInterface;
public function addAction(Request $request, SessionInterface $session) {
// [...]
# there are duplicates
if (!empty($duplicates)) {
$data = $form->getData();
$session->set('prescriber', $data);
$session->set('duplicates', $duplicates);
return $this->forward('AppBundle:Prescriber:addConfirm');
// [...]
}
public function addConfirmAction(Request $request, SessionInterface $session) {
$em = $this->getDoctrine()->getManager();
$p = $session->get('prescriber');
$duplicates = $session->get('duplicates');
// empty form with only a CSRF field
$form = $this->createFormBuilder()->getForm();
if ($form->handleRequest($request)->isValid()) {
$em->persist($p);
$em->flush();
$this->addFlash('p_success', 'The prescriber has been created successfully');
return $this->redirectToRoute('prescriber');
}
// show confirm page
return $this->render('prescribers/form-step2.html.twig', array(
'form' => $form->createView(),
'prescriber'=> $p,
'duplicates'=> $duplicates
));
}

Use the same entity form but two times in Symfony 2

I would like to use the same entity form but two times (to modify two differents properties of my entity). By example, I have a entity User, I create a form to modify the name and another to modify the first name on the same page (just an idiot example). If I submit the first form, it said me that I have extra fields (that is normal). I tried to change the action of the second form with setAction by example but i don't know how to retrieve the form in my controller action.
I started with this code :
$form = $this->createFormBuilder($user)
->add('name', TextareaType::class, array("required" => false))
->add('save', SubmitType::class, array('label' =>'Enregistrer'))
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();
return $this->redirectToRoute('myroute');
}
$form2 = $this->createFormBuilder($user)
->add('fname', TextareaType::class, array("required" => false))
->add('save', SubmitType::class, array('label' =>'Enregistrer'))
->getForm();

How to make a Symfony GET form redirect to route with parameter?

I want to create a form for searching a profile by username which redirect then to the profile page of the user. Btw, I use Symfony 3.2.
I reckon the natural way for doing this would be a GET action form. It would even allow a customer to change the url directly with the good username to see its profile.
Here is the code of my controller :
ProfileController.php
//...
/** #Route("/profil/search", name="profil_search") */
public function searchAction() {
$builder = $this->createFormBuilder();
$builder
->setAction($this->generateUrl('profil_show'))
->setMethod('GET')
->add('username', SearchType::class, array('label' => 'Username : '))
->add('submit', SubmitType::class, array('label' => 'Search'));
$form = $builder->getForm();
return $this->render('profils/profil_search.html.twig', [
'form' => $form->createView(),
]);
}
/** #Route("/profil/show/{username}", name="profil_show") */
public function showAction($username) {
$repository = $this->getDoctrine()->getRepository('AppBundle:User');
$searchedUser = $repository->findOneByUsername($username);
return $this->render('profils/profil_show.html.twig', [
'searchedUser' => $searchedUser,
]);
}
//...
This code will lead to the following error message :
Some mandatory parameters are missing ("username") to generate a URL for
route "profil_show".
I read the documentation thoroughly but couldn't guess, how can I pass the username variable to the profil_show route as a parameter ?
If my way of doing is not the good one, thanks for telling me in comments but I'd still like to know how to use GET forms.
EDIT :
Thanks to #MEmerson answer, I get it now. So for future noobs like me, here is how I did it :
/** #Route("/profil/search", name="profil_search") */
public function searchAction(Request $request) {
$data = array();
$builder = $this->createFormBuilder($data);
$builder
//->setAction($this->generateUrl('profil_show'))
//->setMethod('GET')
->add('username', SearchType::class, array('label' => 'Username : '))
->add('submit', SubmitType::class, array('label' => 'Search'));
$form = $builder->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
return $this->redirectToRoute('profil_show', array('username' => $data["username"]));
}
return $this->render('profils/profil_search.html.twig', [
'method' => __METHOD__,
'form' => $form->createView(),
'message' => $message,
]);
}
If you take a look at the error message it says that the problem is where you are trying to generate the URL for the path 'profil_show'.
Your controller annotations require that the URL be populated with a user name
/** #Route("/profil/show/{username}", name="profil_show") */
this means that Symfony is expecting http://yoursite.com/profil/show/username for the route. But if you want to pass it as a GET form posting it really should be expecting http://yoursite.com/profil/show?username
you can add a second route or change your existing route to be
/** #Route("/profil/show", name="profil_show_search") */
that should solve your problem.

Symfony2 Form Entity Update

Can anyone please show me a specific example of a Symfony2 form entity update? The book only shows how to create a new entity. I need an example of how to update an existing entity where I initially pass the id of the entity on the query string.
I'm having trouble understanding how to access the form again in the code that checks for a post without re-creating the form.
And if I do recreate the form, it means I have to also query for the entity again, which doesn't seem to make much sense.
Here is what I currently have but it doesn't work because it overwrites the entity when the form gets posted.
public function updateAction($id)
{
$em = $this->getDoctrine()->getEntityManager();
$testimonial = $em->getRepository('MyBundle:Testimonial')->find($id);
$form = $this->createForm(new TestimonialType(), $testimonial);
$request = $this->get('request');
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
echo $testimonial->getName();
if ($form->isValid()) {
// perform some action, such as save the object to the database
//$testimonial = $form->getData();
echo 'testimonial: ';
echo var_dump($testimonial);
$em->persist($testimonial);
$em->flush();
return $this->redirect($this->generateUrl('MyBundle_list_testimonials'));
}
}
return $this->render('MyBundle:Testimonial:update.html.twig', array(
'form' => $form->createView()
));
}
Working now. Had to tweak a few things:
public function updateAction($id)
{
$request = $this->get('request');
if (is_null($id)) {
$postData = $request->get('testimonial');
$id = $postData['id'];
}
$em = $this->getDoctrine()->getEntityManager();
$testimonial = $em->getRepository('MyBundle:Testimonial')->find($id);
$form = $this->createForm(new TestimonialType(), $testimonial);
if ($request->getMethod() == 'POST') {
$form->bindRequest($request);
if ($form->isValid()) {
// perform some action, such as save the object to the database
$em->flush();
return $this->redirect($this->generateUrl('MyBundle_list_testimonials'));
}
}
return $this->render('MyBundle:Testimonial:update.html.twig', array(
'form' => $form->createView()
));
}
This is actually a native function of Symfony 2 :
You can generate automatically a CRUD controller from the command line (via doctrine:generate:crud) and the reuse the generated code.
Documentation here :
http://symfony.com/doc/current/bundles/SensioGeneratorBundle/commands/generate_doctrine_crud.html
A quick look at the auto-generated CRUD code by the Symfony's command generate:doctrine:crudshows the following source code for the edit action
/**
* Displays a form to edit an existing product entity.
*
* #Route("/{id}/edit", name="product_edit")
* #Method({"GET", "POST"})
*/
public function editAction(Request $request, Product $product)
{
$editForm = $this->createForm('AppBundle\Form\ProductType', $product);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('product_edit', array('id' => $product->getId()));
}
return $this->render('product/edit.html.twig', array(
'product' => $product,
'edit_form' => $editForm->createView(),
));
}
Note that a Doctrine entity is passed to the action instead of an id (string or integer). This will make an implicit parameter conversion and saves you from manually fetching the corresponding entity with the given id.
It is mentioned as best practice in the Symfony's documentation