Repopulating user inputs after successful validation - validation

I am trying to create a search form where the user has to select from some dropdown menus and enter text in one of a few fields. The problem is I am redisplaying the search page with results below it. To do this I am not redirecting, I am just returning a view with the datasets I need compacted along with it.
Is there any way to get to retrieve input similar to how you would do this Input::old('x') when you were redirecting after failed validation?
The routes are:
Route::get('search', ['as' => 'main.search.get', 'uses' => 'MainController#showSearchPage']);
Route::post('search', ['as' => 'main.search.post', 'uses' => 'MainController#showSearchResults']);
Example of code I have in the view:
{!! Form::open(array('route' => 'main.search.post', 'class' => 'form-inline align-form-center', 'role' => 'form')) !!}
<div class="form-group">
{!! Form::label('product_code', 'Product Code: ',['class' => 'control-label label-top']) !!}
{!! Form::text('product_code', Input::old('product_code'), ['class' => 'form-control input-sm']) !!}
</div>
So when you submit a search, it calls showSearchResults which then returns a view if it succeeds, if it fails validation via my SearchRequest class it gets redirected to the main.search.get route, errors are printed and input is returned to the fields.
I have done a lot of searching and have come up more or less empty handed, it would be nice if there was a way to say ->withInput() when returning a view (not redirecting) or something.
Currently my only solution is to Input::flash() but since I am not redirecting that data persists for an extra refresh. That isn't a terribly big deal at this point, but I was wondering if anyone else had a better solution.
Edit - Code below from controller where view is returned:
...
Input::flash();
return view('main.search', compact('results', 'platformList', 'versionList', 'customerList', 'currencyList', 'customer', 'currency'));
}
Thank you

I had the same problem. The solution that worked for me was to add the following line into the controller.
session(['_old_input' => $request->input()]);
Now I'll explain how it works.
In the view, the global function old() is called:
<input type="username" id="username" class="form-control" name="username" value="{{ old('username') }}" placeholder="Username" autofocus>
This function is in vendor/laravel/framework/src/Illuminate/Foundation/helpers.php
function old($key = null, $default = null)
{
return app('request')->old($key, $default);
}
This calls Illuminate\Http\Request->old():
public function old($key = null, $default = null)
{
return $this->session()->getOldInput($key, $default);
}
Which calls Illuminate\Session\Store->getOldInput():
public function getOldInput($key = null, $default = null)
{
$input = $this->get('_old_input', []);
return Arr::get($input, $key, $default);
}
This call is looking for _old_input in the session. So the solution is to add the input to the session using this value.
Hope this helps.

You can use request instead of old since its the post request
change {{old('product_code')}} to {{request('product_code')}}

Related

Laravel : how to get $payment_gateway value

I'm trying to create a feature where, when i create a new booking i can choose the payment method like via xendit or transfer. But when i tried to submit the output of the payment method is still offline payment because of this code {{$row->gatewayObj ? $row->gatewayObj->getDisplayName() : ''}} , and not xendit. How do i fix this??
The Controller :
public function create(Request $request){
// $this->checkPermission('news_create');
$allServices = get_bookable_services();
$whatsAppBookableServices = ["art", "food", "gear", "car", "hotel"];
$payment_gateway = ["xendit", "offline payment"];//tambahan Nicho
$row = new BookingOffline();
$row->fill([
'status' => 'publish',
]);
$data = [
// 'categories' => NewsCategory::get()->toTree(),
'row' => $row,
'breadcrumbs' => [
[
'name' => __('Report'),
'url' => 'admin/module/report/booking'
],
[
'name' => __('Add Booking By WA'),
'class' => 'active'
],
],
'bookableServices' => array_keys($allServices),
'whatsAppBookableServices' => $whatsAppBookableServices,
'payment_gateway' => $payment_gateway,//tambahan Nicho
];
return view('Report::admin.booking.create', $data);
}
The Blade file :
<td>
{{$row->gatewayObj ? $row->gatewayObj->getDisplayName() : ''}}
</td>
The gatewayObj :
function get_payment_gateway_obj($payment_gateway)
{
$gateways = get_payment_gateways();
if (empty($gateways[$payment_gateway]) or !class_exists($gateways[$payment_gateway])) {
return false;
}
$gatewayObj = new $gateways[$payment_gateway]($payment_gateway);
return $gatewayObj;
}
There are still missing pieces to the puzzle, so I cannot provide you with a code snippet to implement.
However, I think you should be able to diagnose it this way:
Check your controller.
Do a die-dump of the $data just above the line containing return view.... Like so: dd($data['payment_gateway'])
Then refresh the page in your browser and see if the $data object is exactly how you want it. The value should be ["xendit", "offline payment"].
Check your form
I suppose you have a form element like a <select></select>, which is iterating over the values of the $data['payment_gateway'] array. If you do not have this, how are your users choosing between the payment options?
Next, make sure that each iteration of payment gateway is being submitted properly. YOu did not include the snippet that handles form submission, but if you're using a <select> element, the options each need to be submitted with a value.
If we hardcode the select, you will have something like this:
<select name="payment_gateway">
<option value="xendit">Xendit</option>
<option value="offline">Offline Payment</option>
</select>
So when the server receives this form information, it knows the exact value of payment gateway to use. Dynamically, it could look like this:
<select name="payment_gateway">
#foreach($data['payment_gateways'] as $gateway)
<option value="{{ $gateway }}">{{ $gateway }}</option>
#endforeach
</select>
Intercept the request and check that your payment_gateway is being submitted properly.
Go to the controller method that handles your form, and do something like dd($request->all())
Then inspect the value of payment_gateway.

laravel prefil form inputs from controller

Hi I'm using laravel forms.
{!! Form::text('product_name', null, array('class' => 'form-control date_pick')) !!}
Is there a way to set this default input from controller?. Think we can do it with Flash but I couldn't find an example. I want to take vlues from a model and prepopulate.
$products = Products::all();
It would be great if someone know how to do this. What is the easiest way to do it?
This is done with a basic edit route where you simply use:
In ModelController you would call the edit page:
public function edit(ModelName $model) {
return view('name.of.the.blade.view', compact('model')); // if using compact then without dollar symbol
}
In blade view simply make the form with all the input fields you have for that model:
{!! Form::model($model, ['method' => 'PATCH', 'route' => ['model.update', $model->id],]) !!}
Now all the form fields will have the values from that model.
{!! Form::close() !!}
And the edit and update route (inside routes/web.php) would be like this:
Route::get('/model/{model}/edit', 'ModelController#edit')->name('model.edit');
Route::patch('/model/{model}', 'ModelController#update')->name('model.update');

How to clear form input after save?

How can I clear form input on form submit?
After URL is saved I return the view for creating a form so I can add new URL.
The problem is that this time URL is populated from previous save.
How can I empty it after save?
Isn't that the point of second parameter which is set to null?
Using laravel version 5.4.36.
In the "create" iew I have a form with URL input:
{!! Form::open(['route' => 'urls.store']) !!}
{{ Form::url('url', null, array('class' => 'form-control')) }}
{{ Form::submit('Add domain', array('class' => 'btn' )) }}
Store method saves URL to database and returns the same view:
public function store(Request $request)
{
// URL Validation
$this->validate($request, array(
'url' => 'required|url|unique:urls'
));
// Save
$url = new Url;
$url->url = $request->url;
$url->save()
return view('urls.create');
}
Your form view should be handled by a get request on Route and submitting form is a post request .So after submitting the form you should redirect the same page not just returning the view . Check the web.php is the Routes are ok or not . Try to
add it to the store method ,I think it may help you
return redirect()->back();
or with flash message
return redirect('urls.create')->with('success', 'URL has been added');
you can make value = some values come from the controller with empty values when it's the parameters is set i.e use isset function
or
you can make a flag in the view when it sends to controller check it if it is true means you submit the form, in this case, make the values with empty

Laravel Editing post doesn't work

There are routes
Route::get('posts', 'PostsController#index');
Route::get('posts/create', 'PostsController#create');
Route::get('posts/{id}', 'PostsController#show')->name('posts.show');
Route::get('get-random-post', 'PostsController#getRandomPost');
Route::post('posts', 'PostsController#store');
Route::post('publish', 'PostsController#publish');
Route::post('unpublish', 'PostsController#unpublish');
Route::post('delete', 'PostsController#delete');
Route::post('restore', 'PostsController#restore');
Route::post('change-rating', 'PostsController#changeRating');
Route::get('dashboard/posts/{id}/edit', 'PostsController#edit');
Route::put('dashboard/posts/{id}', 'PostsController#update');
Route::get('dashboard', 'DashboardController#index');
Route::get('dashboard/posts/{id}', 'DashboardController#show')->name('dashboard.show');
Route::get('dashboard/published', 'DashboardController#published');
Route::get('dashboard/deleted', 'DashboardController#deleted');
methods in PostsController
public function edit($id)
{
$post = Post::findOrFail($id);
return view('dashboard.edit', compact('post'));
}
public function update($id, PostRequest $request)
{
$post = Post::findOrFail($id);
$post->update($request->all());
return redirect()->route('dashboard.show', ["id" => $post->id]);
}
but when I change post and click submit button, I get an error
MethodNotAllowedHttpException in RouteCollection.php line 233:
What's wrong? How to fix it?
upd
opening of the form from the view
{!! Form::model($post, ['method'=> 'PATCH', 'action' => ['PostsController#update', $post->id], 'id' => 'edit-post']) !!}
and as result I get
<form method="POST" action="http://mytestsite/dashboard/posts?6" accept-charset="UTF-8" id="edit-post"><input name="_method" type="hidden" value="PATCH"><input name="_token" type="hidden" value="aiDh4YNQfLwB20KknKb0R9LpDFNmArhka0X3kIrb">
but why this action http://mytestsite/dashboard/posts?6 ???
Try to use patch instead of put in your route for updating.
Just a small tip you can save energy and a bit of time by declaring the Model in your parameters like this:
public function update(Post $id, PostRequest $request)
and get rid of this
$post = Post::findOrFail($id);
EDIT
You can use url in your form instead of action :
'url'=> '/mytestsite/dashboard/posts/{{$post->id}}'
Based on the error message, the most probable reason is the mismatch between action and route. Maybe route requires POST method, but the action is GET. Check it.
Try to send post id in hidden input, don't use smt like that 'action' => ['PostsController#update', $post->id]
It contribute to result action url.

Redirect back to same page (with variables) on form submit in Laravel 5

On my page events.index, I first display a list of events for the logged on user.
On my index page I have a form with option/select to let the user select and display the events of another user. When he submits that form, I would like my index function (controller) to use the $user_id value (from the form) and display the events.index page again, but for events of that selected user.
I'm not sure what would be the best approach:
Set a session variable to keep the user_id value? Not sure how to do that with a form.
Submit the form with a get method (and get an ugly ?user_id=1 URL)
Change my index route to accept the post method (although I already have that post/events route taken (by Route::post('events', 'EventsController#store'))
Not sure what would be a clean way to do this:
My route for events/index:
Route::get('events', [
'as' => 'event.index',
'uses' => 'EventsController#index'
]);
Events Controller
public function index()
{
// How to get the $user_id value from form?
if (empty($user_id))
{
$user_id = \Auth::user()->id;
}
$events = Event::where('events.user_id','=','$user_id');
$users = User::all();
return view('events.index')->with(['events' => $events])->with(['users' => $users]);
}
View for index
{!! Form::open(['route' => 'events.index', 'method' => 'get']) !!}
<select id="user_id" name="user_id">
#foreach($users as $user)
<option value="{{$user->id}}">{{$user->name}}</option>
#endforeach
</select>
{!! Form::submit('Show events for this user') !!}
{!! Form::close() !!}
#foreach($events as $event)
...
#endforeach
You can get the user_id from a Request object, you just need to inject it in the index method:
public function index(Request $request)
{
$user_id = $request->get('user_id') ?: Auth::id();
$events = Event::where('events.user_id','=','$user_id')->get();
$users = User::all();
return view('events.index')->with(['events' => $events])->with(['users' => $users]);
}

Resources