Getting form values of same form using twig - forms

I'm adding a confirm details dialogue to a form before it gets submitted, using a bootstrap modal.
The form inputs look as follows:
<input type="email" ... name="email" id="email" value="{{ submitted.email }}"/>
I'd like to add a line of text to the modal body which reads something like:
"Send to foo#bar.com?"
I tried the these:
<p>Send to {{ form.email.get('value') }}</p>
<p>Send to {{ form.vars.value.email }}</p>
<p>Send to {{ submitted.email }}</p>
The modal is inside the form which has the input i.o.w:
<form method="post" ...>
...
<input type="email" ..../>
...
<button type="button" data-target="thisModal" data-toggle="modal"> Open Modal </button>
<div id="thisModal" class="modal"...>
...
<div class="modal-body>
<p>Send to {{ XXXXXXX }}</p>
</div>
<div class="modal-footer">
<button type="submit"> Send </button>
</div>
</div>
</form>
Using all 3 prior methods it was simply an empty string, is it possible to grab those values in this way, if so any guidance would be appreciated.

You can handle submitted form data in twig in this way:
{{ YOUR_FORM_VARIABLE.FORM_VARIABLE.vars.value }}
Do not forget to handle form request in your controller, after submitting data.
For sample:
// Some controller
public function indexAction(Request $request)
{
// supposing that FormType has only email field
$form = $this->createForm(FormType::class, null, array(
'action' => $this->generateUrl('homepage'),
));
$form->handleRequest($request);
return $this->render('Bundle:Homepage:layout.html.twig', array(
'form' => $form->createView()
));
}
And in template:
// Bundle:Homepage:layout.html.twig
{{ form(form) }}
<b>{{ dump(form.email.vars.value )}}</b>

The modal is being called via JavaScript so it doesn't hit PHP at the point wherein which the data needs to be transferred. Hence it cannot be done using twig, as the data is yet to be passed.

Related

Symfony flash message and data not refreshed after submission of a form

I am using a modal form to update an address. Everything is working properly except that the flash message is not displayed or the view data updated after the form is submitted and therefore the page reloads. For the message to appear and the data to be updated, I have to manually refresh the page.
Here is the call of the modal form in my view :
...
{{ include('_flashMessages.html.twig') }}
...
Edit
...
<div id="profileAddress" tabindex="-1" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Profile address</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
{{ render(controller('App\\Controller\\user\\ProfileController::editAddress', { 'advert': advert.id, 'request': app.request })) }}
</div>
</div>
</div>
</div>
...
Here is the function called to render the form :
/**
* #Route("/user/profile/show/{id}", name="user.profile.show")
*
* #return Response
*/
public function show(User $user): Response
{
$profile = $user->getProfile();
return $this->render('user/profile/show.html.twig', array(
'profile' => $profile,
'bodyId' => 'profileShow'
)
)
;
}
And finally, here is the action that I linked to my form to redirect to the initial view :
{{ form_start(form, { 'action': absolute_url(path('advert.vehicle.create', { 'id': advert.id })), 'attr': { 'id': 'profileAddressForm' } }) }}
...
Anyone have an idea of the cause of the flash message not being displayed and the address data not being updated in the initial view?
Thank you in advance for your help.
EDIT :
I solved 1 problem out of 2: by placing my modal div at the start of the template, the success flash message is now displayed correctly after submitting the form.
It remains now to understand why the data which has been correctly updated via the use of the said form is not refreshed in my view. Indeed, in this one, I have :
...
{% set profileAddress = advert.owner.user.profile.address.street %}
...
<div class="row">
<div class="col-md-10">
{{ form_row ( vehicleForm.situation.useProfileAddess, { 'id':'use_profil_address', 'label': "Use my profile address (" ~ profileAddress ~ ")" } ) }}
</div>
<div class="col">
Edit
</div>
</div>
...
The form updates the address data in the database, but these are not refreshed in the view when the page reloads after the form is submitted.
Resolved by
{% set profileAddress = advert.owner.user.profile.address %}
and
{{ form_row ( vehicleForm.situation.useProfileAddess, { 'id':'use_profil_address', 'label': "Use my profile address (" ~ profileAddress.street ~ ")" } ) }}

Laravel 5.8: Two round passing data between controller and blade

I am getting undefined variable when passing data from controller to blade the second time.
With Laravel 5.8, I have two actions/methods in a MyController. I have to pass data from controller to view. The first action works fine (MyController#action1 -> Blade1) but the second fails (MyController#action2 -> Blade2).
MyController:
public function action1()
{
...
$varialbe1 = ... // everything set correctly here and got it in blade1
return view('blade1', compact('variable1'));
}
public function action2(Request $request)
{
...
$association = $request->input('association');
return view('blade2', compact('association'));
}
Blade 1
<form method="POST" action="{{ route('route2') }}">
#csrf
<div class="form-group row">
<label for="association" class="col-md-4 col-form-label text-md-right">{{ __('Association') }}</label>
<div class="col-md-6">
<select required="required" id="association" class="form-control" name="association">
<option></option>
#foreach ($variable1 as $key => $val)
<option value="{{ $key }}">{{ $val->id }}</option>
#endforeach
</select>
</div>
</div>
<div class="form-group row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Submit') }}
</button>
</div>
</div>
</form>
Route
Route::post('/route2', 'MyController#action2')->name('route2');
Blade 2 (Undefined variable: association)
{{ $association }}
I have tried different ways to get data in MyController and different to pass data to Blade2 (the way that also works fine with the action1), including:
$association = Input::get('association');
return redirect()->to('/route2')->with('association', $association); // where route2 load the view
My route file seems good (MyController in the previous post = LoginController). Here is my route/web.php:
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', 'HomeController#index')->name('home');
Route::post('/route2', 'Auth\LoginController#action2')->name('route2');
Got resolved from another forum.
Should add the action method to the list of exception methods in the middleware as follow:
$this->middleware('guest')->except(['logout', 'action']);
As controller has the below middleware in the constructor:
$this->middleware('guest')->except('logout');
If the User is already logged in, which is the case, they will be redirected to the /home and the controller method will never be reached.

FormFacade class doesn't load Bootstrap classes in Laravel 5.5

I'm trying to load Bootstrap classes with FormFacade in a view but doesn't work.
I tried this steps: https://stackoverflow.com/a/46392838/3444714
But the Form class is generating fields without the effects of Bootstrap.
<div class="form-group">
{{ Form::label('testField', 'Test:') }}
{{ Form::text('testField', null, ['class' => 'form­-control']) }}
<input type="text" id="testField" name="testField" class="form-control" />
</div>
Check my attachment, same code, but the field generated by FormFacade is wrong.
Thank you.

Render issue when validation fail with 2 forms on the same page

i need to render 2 forms on the same page. To do this, I have 2 actions in my controller, the first one manage the form 1 and render the entire page, the second manage the form 2 and render only this form.
The second action is called in twig with a :
{% render (controller("AppBundle:User:secondForm")) %}
Both are rendered, both work, excepted when the validation of the form 2 fail. The Controller return the user to the form with form errors but instead of returning to the entire page, it only render the form.
My code look like this :
First action:
/**
* #Route("/profile/global-page", name="global_page")
*/
public function Global1Action(Request $request)
{
[.......]
$process = $formHandler->process($user);
if ($process) {
$request->getSession()->getFlashBag()->add('success', 'ok');
return $this->redirect($this->generateUrl('an_url'));
}
return $this->render('entire_page.html.twig', array(
'form' => $form->createView(),
));
}
then Twig global (entire_page.html.twig):
{% extends 'base.html.twig' %}
{% block content %}
{#FlashBags#}
{% include 'components/alert.html.twig' with {'type':'success'} %}
<div class="col-md-offset-3 col-md-6">
<div class="col-md-12 row">
<div class="panel panel-profil">
<div class="panel-heading">
<h3 class="panel-title">form 1</h3>
</div>
<div class="panel-body">
<form action="{{ path('global_page') }}" method="POST" class="form-horizontal text-center">
{{ form_widget(form) }}
<button type="submit" name="submit" class="btn btn-main button-sm">Go</button>
</form>
</div>
</div>
</div>
</div>
{% render (controller("AppBundle:User:secondForm")) %}
{% endblock %}
then SecondForm action:
/**
* #Route("/profile/second-form", name="second_form")
*/
public function secondFormAction(Request $request)
{
[.......]
$process = $formHandler->process($user);
if ($process) {
$request->getSession()->getFlashBag()->add('success', 'ok');
return $this->redirect($this->generateUrl('an_url'));
}
return $this->render('only_form2.html.twig', array(
'form' => $form->createView(),
));
}
and finaly the second twig (only_form2.html.twig):
<div class="col-md-offset-3 col-md-6">
<div class="col-md-12 row">
<div class="panel panel-profil" style="margin-top: 10px;">
<div class="panel-heading">
<h3 class="panel-title"> second form panel </h3>
</div>
<div class="panel-body">
<form action="{{ path('second_form') }}" {{ form_enctype(form) }} method="POST">
{{ form_widget(form) }}
<button type="submit" name="submit" class="btn btn-main button-sm">Go 2</button>
</form>
</div>
</div>
</div>
I don't understand how to return the user to the entire page (with form errors) instead of rendering only the second form when it's validation fail.
Thank you !
Edit: I found this post which explain how to have 2 forms in one controller. Answer below seems to not work with Symfony 2.8
You can use a multi form action. Something like this :
public function multiformAction()
{
$form1 = $this->get('form.factory')->createNamedBuilder($formTypeA, 'form1name')
->add('foo', 'text')
->getForm();
$form2 = $this->get('form.factory')->createNamedBuilder($formTypeB, 'form2name')
->add('bar', 'text')
->getForm();
if('POST' === $request->getMethod()) {
if ($request->request->has('form1name') {
// handle the first form
}
if ($request->request->has('form2name') {
// handle the second form
}
}
return array(
'form1' => $form1->createView(),
'form2' => $form2->createView()
);
}
See this post. And this question
To solve this issue you need to send Form request to action where render whole page (Global1Action). Not to action where second form is created.
You will need also move both forms handling to Global1Action.
To change second form action use this method:
$form->setAction($this->generateUrl('global_page'))
Or you can implement ajax handling for second form (if you need to keep it's logic in separate action).

How to delete an entity from a template with a list of entities (CRUD)?

Explanation:
I have generated the CRUD of an entity, getting the following default actions:
indexAction(): lists all entities.
showAction($id): finds (by ID) and displays an entity.
deleteAction($id): deletes an entity.
another actions.
So, I have seen I can only delete an entity within the actions that use the param $id (e.g.: showAction($id) ) but I want to delete an entity inside the indexAction template because I save a step to users.
The deleteAction needs a request, an ID and use the POST method.
I was trying to code something like:
<a href="{{ path('entity_delete', { 'id': entity.id }) }}" class="btn">
<img src="{{ asset('bundles/acme/images/delete.png') }}" ... />
</a>
When I execute the action, I get the following error:
No route found for "GET /acme/something/4/delete": Method Not Allowed
(Allow: POST, DELETE)
This response is clear and it's what I expected, so I tried to do something similar but using a form. Something like this:
<form id="formDelete" action="{{ path('entity_delete', { 'id': entity.id }) }}" method="post">
<input type="hidden" name="_method" value="DELETE" />
{{ form_widget(delete_form) }}
<a href="{{ url('entity_delete') }}" class="btn" onclick="document.getElementById('formDelete').submit();">
<img src="{{ asset('bundles/acme/images/delete.png') }}" ... />
</a>
</form>
But the line {{ form_widget(delete_form) }} is a problem because the indexAction() hasn't got any parameter and it needs this code:
$deleteForm = $this->createDeleteForm($id);
return $this->render('AcmeBundle:Demo:index.html.twig', array(
'entities' => $entities,
'delete_form' => $deleteForm->createView(),
));
As you can see, the $id param is mandatory for the method createDeleteForm($id) but I can't get it from indexAction().
Question:
What is the best way to solve this issue?
if you only want to have as much delete buttons as items in your index here's how to easily do it.
In the indexAction, add the following loop and don't forget to pass the parameter to the view.
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('FooBundle:Link')->findAll();
$deleteForms = array();
foreach ($entities as $entity) {
$deleteForms[$entity->getId()] = $this->createDeleteForm($entity->getId())->createView();
}
return array(
'entities' => $entities,
'deleteForms' => $deleteForms,
);
}
Basicaly I just loop over all my entities and create the corresponding delete form using the built-in method generated by the crud, storing each form in an array and passing it to the view.
Then in the view, just add the form already available in the edit.html.twig generated view and edit the form_widget's parameter:
<form action="{{ path('foo_delete', { 'id': entity.id }) }}" method="post">
<input type="hidden" name="_method" value="DELETE" />
{{ form_widget(deleteForms[entity.id]) }}
<button type="submit" class="btn btn-small">
<i class="icon-trash"></i>
{{ 'links.admin.form.delete' | trans({}, 'FooBundle') }}
</button>
</form>