Rendering data from a form to a another view in Symfony 5 - forms

I am making several loan calculators in Symfony 5, all are in my controller SimulatorController.
The user is filling up / submitting a form in the View 1 and should land on View 2 where calculations results appear, along with a recpa of data entered in the form.
So I have a first function in my controller which creates the calculation form, make some calculations, render the form into the view 1 and redirects to View 2 once the form is submitted :
#[Route('/rachat-credits', name: 'app_rachat')]
public function rachat(Request $request)
{
// Debts rate
$form = $this->createForm(SimulDebtFormType::class);
$debtForm = $form->handleRequest($request);
if($debtForm->isSubmitted() && $debtForm->isValid()){
$wages = $debtForm->get('salaries')->getdata();
$bonuses = $debtForm->get('bonuses')->getdata();
$earnings = $debtForm->get('earnings')->getdata();
$expenses = $debtForm->get('expenses')->getdata();
$totalIncome = intval($wages + $bonuses + $earnings);
$rate = floatval($expenses/$totalIncome*100);
$debtRate = number_format($rate, 2,',',' ');
$rest = $totalIncome - $expenses;
$restToLive = number_format($rest,0,'',' ');
return $this->redirectToRoute('app_simul_res_endet');
}
return $this->render('Simul/rachat.html.twig', [
'debtrateform' => $debtForm->createView(),
]);
}
And a second function to render the View 2, which displays the results from the previous a form and create a contact form on it.
I don't manage to pass the retrieved and calculated data into the View 2, I tried to enter parameters in an array into redirectToRoute(), such as:
return $this->redirectToRoute('app_simul_res_endet', [
'debtRate' => $debtRate,
'restToLive' => $restToLive,
'totalIncome' => $totalIncome,
'expenses' => $expenses,
]);
but the View 2 did not recognized the variables.
<div class="row justify-content-evenly align-items-center text-center fw-bold m-3 endettement">
<div class="col-sm-6 col-md-4 rounded-3 p-4 mb-4 data">
<div class="row justify-content-around align-items-center fw-bold">
<div class="col-10 text-start">
<p>Mes revenus mensuels</p>
<p>Mes charges mensuelles</p>
</div>
<div class="col-1 text-end figures">
<p>{{ totalIncome }}€</p>
<p>{{ expenses }}€</p>
</div>
</div>
</div>
<div class="col-sm-6 col-md-4 results rounded-3 p-4">
<h3>Estimation de votre
taux d'endettement*</h3>
<h3 class="mensualite">{{ debtRate }}%</h3>
<h3 class="mt-4">Reste à vivre*</h3>
<h3 class="mensualite">{{ restToLive }}€</h3>
<button class="btn ctaWhite text-uppercase rounded-pill mt-4">Recalculer</button>
</div>
</div>
Anyone has a clue or advice on how to proceed?

Related

storing form and rout

I have problem on storing form . All my efforts will be damaged if I could not solve it.
The GET method is not supported for this route. Supported methods: POST.
what happen now :
1.When I press on register which is linked to this rout :
Route::POST('/jobs/apply/{id}/', [JobseekerController::class,'applyforjob'])->name('aplpy1');
there will be two scenarios:
if the user has cv it will register the user directly.(works)
if the user has not cv it will direct the user to create cv view .(works)
This is a part of create cv view :
<form method="POST" action="{{route('storing')}}" enctype=multipart/form-data>
#csrf
<input type="hidden" name=job_id value= {{$s}}>
#if (count($errors) > 0)
<div class="alert alert-danger alert-dismissible fade show">
<strong>Opps!</strong> Something went wrong, please check below errors.<br><br>
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
#endif
<div class="card-body">
<div class="container">
<!------ Include the above in your HEAD tag ---------->
<div class="container">
<div class="row">
<div class="col-md-12">
<div id="accordion" class="checkout">
<div class="panel checkout-step">
<div> <span class="checkout-step-number">1</span>
<h4 class="checkout-step-title"> <a role="button" data-toggle="collapse" data-parent="#accordion" href="#collapseOne" > Personal Information</a></h4>
</div>
<div id="collapseOne" class="collapse in">
<div class="checkout-step-body">
<div class="row mt-3 pr-3">
<div class="col-6 ">
<strong>Full Name:</strong>
{!! Form::text('FName', null, array('placeholder' => 'Full Name','class' =>
'form-control pb-4')) !!}
</div>
<div class="col-6">
<div class="row mt-3 mr-2">
<strong>Nationality:</strong>
<select name="Nationality" class="custom-select">
#foreach(\App\Models\Nationality::all() as $nation)
<option value="{{$nation->name}}">{{$nation->name}}</option>
#endforeach
</select>
</div>
<div class="form-group ">
<button type="submit" name="submit" class="btn btn-primary ">{{ __('APPLAY') }}</button
</div>
<input type="hidden" name=job_id value= {{$s}}>
</form>
2.Now Here is the problem:
If I fill all the fields on the form correctly and click apply it works , but if there is missing field or anything not filled as it should be and then click apply , although there is validation on controller it does not work it gives this error:
The GET method is not supported for this route. Supported methods: POST.
Although I am using Post this my rout that I use to store the form
Route::POST('/jobsapply', [JobseekerController::class,'store'])->name('storing');
This my controller for storing:
public function store(Request $request )
{
$this->validate($request, [
'FName' => 'required|alpha|regex:/^([^"!\*\\]*)$/',
'Nationality' => 'required',
]);
$input = $request->all();
$input = $request->except(['_token']);
$cv = new cv();
if ($this->cvsave($cv, $request )) {
$data = Job::all();
$cv = auth()->user()->cv;
return view ('show',compact('cv' ,'data'))->with('success', 'CV created successfully.');
}
$data = Job::all();
return view('show')->with('Failed!', 'error');
}
public function cvsave(cv $cv, Request $request)
{
$cv->FName = $request->FName;
$cv->Nationality = $request->Nationality;
if ($cv->save()) {
$application = new JobApplication;
$id=$request->job_id;
$jobs = Job::find($id)->get();
$application->job_id =$request->job_id;
$user = User::find(auth()->user()->id);
$application->user_id = auth()->user()->id;
$cv = auth()->user()->cv;
$i= $cv->id;
$application->cv_id = $i;
$application->save();
\Session::flash('success', 'Thank you for applying! Wait for the company to respond.!');
return true;
}
return false;
}
I could not know the reason, I have read lots of stuff but still the same error

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 ~ ")" } ) }}

My form is not populating when there is some validation error in the input data. Laravel Collective

Hope yo are all doing great.
I am using Laravel 5.3 and a package LaravelCollective for form-model binding.
I have subjects array that I want to validate and then store in database if there is no error in the input data.
The following snippets show the partial view of form, other views, rules for validations and controller code.
UserProfile.blade.php
<!-- Panel that Adds the Subject - START -->
<div class="col-md-12">
<div class="panel panel-default" id="add_Subject_panel">
<div class="panel-heading">Add Subject(s):</div>
<div class="panel-body">
{!! Form::open( array('method'=>'post', 'url'=>route('user.store.subject', 1)) ) !!}
#include('user.partials.subjects', ['buttonText'=>'Add Subject(s)'])
{!! Form::close() !!}
</div>
</div>
</div>
<!-- Panel that Adds the Subject - END -->
subjects.blade.php
#if (count($errors) > 0)
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
<div class="subject-list">
<div class="input-group subject-input">
<input type="text" name="name[]" class="form-control" value="" placeholder="Subject" />
<span class="input-group-btn">
<span class="btn btn-default">Primary subject</span>
</span>
</div>
</div>
<div class="text-right">
<br />
<button type="button" class="btn btn-success btn-sm btn-add-subject"><span class="glyphicon glyphicon-plus"></span> Add Subject</button>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-4 text-right">
<button type="submit" class="btn btn-primary">
{{ $buttonText }} <i class="fa fa-btn fa-subject"></i>
</button>
</div>
</div>
#push('scripts')
{{-- <script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script> --}}
<script src="{{ asset('scripts/jquery-2.2.4.min.js') }}" type="text/javascript" charset="utf-8" async defer></script>
<script>
$(function()
{
$(document.body).on('click', '.btn-remove-subject', function(){
$(this).closest('.subject-input').remove();
});
$('.btn-add-subject').click(function()
{
var index = $('.subject-input').length + 1;
$('.subject-list').append(''+
'<div class="input-group subject-input" style="margin-top:20px; margin-bottom:20px;">'+
'<input type="text" name="name['+index+']" class="form-control" value="" placeholder="Subject" />'+
'<span class="input-group-btn">'+
'<button class="btn btn-danger btn-remove-subject" type="button"><span class="glyphicon glyphicon-remove"></span></button>'+
'</span>'+
'</div>'
);
});
});
</script>
#endpush
I want to validate all the subjects passed as an array to the controller using a custom created form request. the following is the code for that form request
SubjectRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class SubjectRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
// dd("Rules Area");
foreach($this->request->get('name') as $key => $val)
{
$rules['name.'.$key] = 'required|min:5|max:50';
}
// dd($rules);
return $rules;
}
public function messages()
{
// dd('Message Area. . .');
$messages = [];
foreach($this->request->get('name') as $key => $val)
{
$messages['name.'.$key.'.required'] = ' Subject Name '.$key.'" is required.';
$messages['name.'.$key.'.min'] = ' Subject Name '.$key.'" must be atleast :min characters long.';
$messages['name.'.$key.'.max'] = ' Subject Name '.$key.'" must be less than :max characters.';
}
// dd($messages);
return $messages;
}
}
the following is the code for controller method I am using to store inputted array data to database.
public function storeSubjects(SubjectRequest $request)
{
$data = $request->all();
// save logic
dd($data);
}
Problem:
My form is not populating when there is some validation error in the input data.
After getting validation errors, my input fields are blank.
Problem
In subject.blade.php, your code looks like
<input type="text" name="name[]" class="form-control" value="" placeholder="Subject" />
Your fields are not populating because you have left value attribute blank.
Solution:
Pass the old value to solve your problem.
<input type="text" name="name[]" class="form-control" value="{{old('name[]')}}" placeholder="Subject" />
Use Form Model Binding instead
https://laravelcollective.com/docs/5.3/html#form-model-binding
{{ Form::model($user, [....]) }}
{{ Form::text('firstname', null, [...]) }}
{{ Form::close() }}

Laravel 4 Preview Form Submit

Any idea how to solve the following approach.
I have a form and want to display the entered data in a specific formtemplate before store it in the DB. If the entered data looks properly, the user can save the form.So I am searching for a way to display the entered data as a preview in a new window/tab first. With my code below I am not able to preview the form without saving the data in the databse. Also display the preview in a new window or tab is not possible. I guess there is no way to achieve this with php / laravel. I tried some onlick events, but no luck. As it seems like the route is prefered.
Any idea how to solve this?
My form looks like:
{{ Form::open(array('url' => 'backend/menubuilder/'.$id, 'method' => 'PUT'))}}
<section>
<div class="container">
<div class="row">
<div class="inputBox">
<div class="col-xs-12 col-md-6">
<h3>Montag</h3>
<div class="form-group">
{{Form::label('gericht_1_mo','Gericht 1')}}
{{Form::textarea('gericht_1_mo', Auth::user()->gericht_1_mo,array('class' => 'form-control'))}}
</div>
<div class="form-group">
{{Form::label('preis_1_mo','Preis', array('class' => 'col-md-6'))}}
{{Form::text('preis_1_mo', Auth::user()->preis_1_mo, array('class' => 'col-md-6'))}}
</div>
<div class="form-group mrgT55">
{{Form::label('gericht_2_mo','Gericht 2')}}
{{Form::textarea('gericht_2_mo', Auth::user()->gericht_2_mo,array('class' => 'form-control'))}}
</div>
<div class="form-group">
{{Form::label('preis_2_mo','Preis', array('class' => 'col-md-6'))}}
{{Form::text('preis_2_mo', Auth::user()->preis_2_mo, array('class' => 'col-md-6'))}}
</div>
</div>
</div>
</div>
</div>
</div>
{{Form::submit('update')}}
{{-- <input type="submit" name="preview" value="preview"> --}}
{{Form::close()}}
{{ Form::open(array('url' => 'backend/menubuilder/templatesview/'.$id, 'method' => 'POST'))}}
{{-- {{Form::submit('Preview',array('onClick' => 'target_blank'))}} --}}
<input onclick="newTab()" type="submit" name="preview" value="preview" >
{{Form::close()}}
My routes:
Route::get('backend/menubuilder/templates/{id}', 'MenuBuilderController#template');
Route::post('backend/menubuilder/templatesview/{id}', 'MenuBuilderController#preview');
My Controller:
public function preview($id)
{
$user = User::find($id);
$owner = (Auth::id() === (int) $id);
return View::make('backend/menubuilder/templatesview/tempone')->withUser($user)->withOwner($owner);
}
public function template($id)
{
$user = User::find($id);
$owner = (Auth::id() === (int) $id);
return View::make('backend/menubuilder/templates/tempone')->withUser($user)->withOwner($owner);
}

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).