How to persist checked items across pagination requests in Laravel? - php

I have a form where I show some items, which can be selected by the user.
There are over 1000 items so I'm using pagination.
What would be the best way to persist the checked items, when user go to the next page?
To store all these items in hidden fields wouldn't be an option, because they are to much items.
My View:
#foreach($articles['uncommitted'] as $article)
<tr>
<td><input type="checkbox" name="articles[]"></td>
<td>{{{$article->articlename}}}</td>
<td>{{{$article->category->catname}}}</td>
<td>{{{strftime('%d.%m.%Y %H:%M', strtotime($article->created_at))}}
<td>{{{$article->rrp}}}</td>>created_at))}}}</td>
</tr>
#endforeach
{{$links}}
This form will be paginated.

As far as I understand you are facing two problems: persisting the checked items across pagination request, and retrieving the checked items back to the view.
To persist the checked items across pagination request, I would flash the checked items into the Session. The controller method will look something as follows.
public function fill_form()
{
$items = Item::paginate(25);
// Retrieve checked items in session.
$checked_items = []
if (Session::has('checked_items'))
$checked_items = Session::get('checked_items');
// Persist new checked items.
$checked_items = array_merge($checked_items, Input::get('item'));
Session::flash('checked_items', $checked_items);
return View::make('form')
->with('items', $items);
}
As you can see the checked items will be available in the session within pagination requests.
Now for the case to display the checked items back to the view I would send the checked items in session to the view via old input. That said, the return value would be changed as follows.
public function fill_form()
{
# code intentionally omitted #
return View::make('form')
->with('items', $items)
->withInput($checked_items);
}
Then in your views the checked items will persist their checked value. Obviously, you should use Laravel to generate your checkboxes.
How to get all item (checked or not) on submit?
Maybe, if you are render items with checkboxes you will need to know which of those checkboxes were checked and which not when paginating. A simply solution will be adding an extra input hidden field for each checkbox with a default value, it will look as follows:
{{ Form::hidden('item1', 'off') }}
{{ Form::checkbox('item1', 'on') }}
{{ Form::hidden('item2', 'off') }}
{{ Form::checkbox('item2', 'on') }}
{{ Form::hidden('item3', 'off') }}
{{ Form::checkbox('item3', 'on') }}
After submitting the form, when paginating, for checked item you will receive the expected value, for those not checked you will receive the hidden value.
Note 1, it is important to put the hidden input before each checkbox.
Note 2, each hidden input should have the same name as the checkbox.

Unless I misunderstood your question, I think what you're looking for is caching: http://four.laravel.com/docs/cache
Here's an excerpt from the docs:
Database Cache
When using the database cache driver, you will need to setup a table to contain the cache items. Below is an example Schema declaration for the table:
Schema::create('cache', function($table)
{
$table->string('key')->unique();
$table->text('value');
$table->integer('expiration');
});
If you're wanting to store form data across requests, then you'll want to use Session - excerpt from the docs (http://four.laravel.com/docs/session):
Database Sessions
When using the database session driver, you will need to setup a table to contain the session items. Below is an example Schema declaration for the table:
Schema::create('sessions', function($table)
{
$table->string('id')->unique();
$table->text('payload');
$table->integer('last_activity');
});

Related

Save fileds changes with ajax in laravel

I want to change some parts of my data from index page without loading edit page with Ajax.
For example my reviews has status where value is 0 or 1 and also comment section. I want to change these values from my index page.
All the code i have is simply my index method only, where i load my list
public function index()
{
$ratings = Rating::orderby('id', 'desc')->paginate(10);
return view('admin.ratings.index', compact('ratings'));
}
I need help to make my index page as a form with Ajax in order to edit from there but not to use my Update method because I'll need it for my edit.blade.php (maybe add another method in my controller?)
Thanks.
First of all you need a controller that updates the post status. As discussed it totally up to you want you want to do.
My suggestion is to create a new controller called UpdatePostStatusController and then have update method that takes post id and the status either 1 or 0 and update it.
Your index file should have javascript that gets triggred everytime you change the status like so
checkbox html
<input type="checkbox" data-uuid="{{ $post->id }}" class="update" #if($post->status) checked #endif/>
Now your ajax should
$('.update').change(function() {
data = {'status' : this.checked }
post_id = $(this).data('uuid');
//do your ajax post request here here
}

Return back from edit form after several updates in Laravel 5.4

I'm trying to add functionality to my edit form. Perhaps not a best practice but...
I want to keep the original url for several updates. When a user first lands on edit form (from list or single view) I want a Cancel button that redirects user back to.. "referrer". After an update I redirect back to edit form with success message. I want to hide the Cancel button and show Back button. User can edit multiple times.
I tried to pass the original url through Request, but that didn't end well. Now I'm trying with storing the url in session. Ifs work, but the session item value gets overwritten in second iteration.
Perhaps I'm using the session the wrong way? Any idea? Perhaps another "better" way?
The code in my edit.blade
#if(url()->current() != URL::previous())
#if(Session::has('myreferrer'))
{{ Session::forget('myreferrer') }}
#endif
{{ Session::put('myreferrer', URL::previous()) }}
Cancel
#else
Back
#endif
Session::pull() fetches the value from the session and removes it. This is why the page doesn't work the second time:
User visits edit from previous
URL::current() != URL::previous()
'myreferrer' set to previous
Show Cancel button
User fills and saves edit form
URL::current() === URL::previous()
'myreferrer' set to null (because Session::pull())
Show Back button
User saves edit form again
URL::current() still === URL::previous()
'myreferrer' is still null
Show Back button again with an empty URL (because 'myreferrer' is null) which the browser interprets as the current URL
We can use Session::get() to fetch the value and leave it in the session, but this pollutes the session because 'myreferrer' still exists when the user navigates away from the edit form.
More importantly, this logic doesn't belong in a view template. Instead we'll use the controller to pass the value of 'myreferrer' using a hidden input field:
public function edit($id)
{
// fetch data...
return view('edit')
// if "myreferrer" isn't in the session yet, use previous URL:
->with('myreferrer', Session::get('myreferrer', URL::previous()));
}
public function update(Request $request)
{
// save data...
return back()
->with('success', 'Your success message.')
// "flashes" to the session only for the next page load:
->with('myreferrer', $request->get('myreferrer'));
}
<form ...>
<input type="hidden" name="myreferrer" value="{{ $myreferrer }}"/>
...
#if (Session::has('success'))
Back
#else
Cancel
#endif
I'm assuming you actually need the previous URL to be dynamic, such as if the user can open the edit form from different pages. Named routes offer better semantics when you don't need this flexibility.
For the sake of learning, here are some other pointers related to your code:
We don't need Session::has() before Session::forget() (forget() skips if the key doesn't exist). Additionally, the call to Session::put() afterward overwrites the value here anyway, so we can remove the whole #if(Session::has('myreferrer')) block.
url()-> and URL:: do the same thing. We should probably choose one for consistency.

Laravel (Beginner) - Display data from a selected row from a dropdown

This is Controller.php
public function dropdown($id)
{
$stations = Station::lists('station_name','id');
return view('stations.show')->withStation($station);
return view('stations.dropdown',compact('stations', 'selectedStation','selectedStation'));
}
This is the view.php
{{ Form::select('station',$stations,null,['class' => 'form-control']) }}
<br>
<?php
if(isset($_GET['submit'])){
$selectedStation = $_GET['station'];
echo $selectedStation;echo "<br>";
}
else
{
echo "not working";
}
?>
corresponding Database table.
This gives me a drop-down like in the below image.
When a station is selected it displays only "id" of the selected station. How to retrieve other columns of the selected station ?.
Many ways that you can tackle this and I have also made some assumptions.
Your list (it would seem) only contains the name & the id.
I assume that you don't want to reload the page when you get the information for the specific item that you have chosen in the dropdown.
Here are the first 2 options that come to mind.
1.) AJAX - Use javascript framework like jQuery and monitor change() for the select, on change get the id and fire it to another route in Laravel which takes the ID and returns some more information in JSON. You can then use JS to display this to your users as you please.
2.) Preloaded JSON - Write new DB Query that gets all the information that you want and store it in JSON format inside some <script> tags. It wont be viewable to the user. Then you can use jQuery or other JS framework to grab that data again on change()
Part 2 will be faster, and if you have got 100,000s records i would advise that for perf.
Apologies if I totally misunderstood the question, it seems like you need a JS solution rather than Laravel/PHP solution. (Without a bad UX) if you did wan't more data you would need to post it and the fetch data from DB on new request.
To display all the columns of all stations you can do the following.
Please note, doing this you fetch all which may not be necessary and there may be better methods available on the eloquent model class depending on what you are trying to do.
Controller
public function showTable()
{
//Fetch all stations from the database
$stations = Station::all();
//Return fetched data to the view
return view('stations.show', ['stations' => $stations]);
}
View - stations/view.blade.php
<ul>
#foreach ($stations as $station)
<li>{{$station->station_name}} - {{$station->rainfall}}</li>
#endforeach
</ul>
For more information and examples about the eloquent model class you can check: https://laravel.com/docs/5.2/eloquent

Laravel: set checkboxes as default set

I have one really simple question. I have a form with three groups of dynamically generated check boxes. Let's say one of these groups of check boxes needs to have all check boxes as default set.
This is not a problem, the problem comes when I submit the form and I need to have the state of the checkbox.
Here is the HTML code I generate:
#for($i=0;$i<24;++$i)
{!! Form::checkbox('check_hour[]', $i, $check_hour[$i], ['class' => 'check_hour']) !!} {{($i+1)}}h
#endfor
and here is the code in the Controller:
for($i=0;$i<24;++$i) $check_hour[$i] = (isset(Input::get('check_hour')[$i])) ? true : false;
In this situation I have no problem to save the checkbox state, but I need all check boxes to bet set as default.

Populating dynamic html elements on validation failure in Laravel 5.1

In my form, I am populating state and city dropdowns using ajax.
Also, on the same form the user can add multiple employees by clicking on the "Add more button".
In both above scenarios the HTML DOM elements are generated using jquery.
I need re-build the dynamically generated elements in case the validation fails on form submit.
Can anyone please tell me a right approach for achieving the above mentioned issue.
Thanks.
Say you've generated a list of inputs dynamically by calling a js function, maybe something like
//JS
function generate(){
$("#container-abc").append("<input name=name[]>");
}
<!--HTML -->
<input name=name[] />
<input name=name[] />
Submit them and if there's validation error you will get back the values using:
//in your blade
$name = Request::old('name');
#if(count($name) > 0)
for (var i = 1; i <= {{count($name)}}; i++) {
generate();
}
#endif
you can use
return Redirect::back()->withInput();
or for more info visit https://laravel.com/docs/5.2/requests#old-input
Old Input
Laravel allows you to keep input from one request during the next
request. This feature is particularly useful for re-populating forms
after detecting validation errors. However, if you are using Laravel's
included validation services, it is unlikely you will need to manually
use these methods, as some of Laravel's built-in validation facilities
will call them automatically. Flashing Input To The Session
The flash method on the Illuminate\Http\Request instance will flash
the current input to the session so that it is available during the
user's next request to the application:
$request->flash();
You may also use the flashOnly and flashExcept methods to flash a
sub-set of the request data into the session:
$request->flashOnly(['username', 'email']);
$request->flashExcept('password');
Flash Input Into Session Then Redirect
Since you often will want to flash input in association with a
redirect to the previous page, you may easily chain input flashing
onto a redirect using the withInput method:
return redirect('form')->withInput();
return redirect('form')->withInput($request->except('password'));
Retrieving Old Data
To retrieve flashed input from the previous request, use the old
method on the Request instance. The old method provides a convenient
helper for pulling the flashed input data out of the session:
$username = $request->old('username');
Laravel also provides a global old helper function. If you are
displaying old input within a Blade template, it is more convenient to
use the old helper. If no old input exists for the given string, null
will be returned:

Categories