blank page in next page in laravel pagination - laravel

Pagination in laravel is showing blank page in pages other than first.
below is controller
$products=DB::table('products')->join('mobile_devices', 'products.id', '=', 'mobile_devices.product_id')->where('mobile_devices.brand', '=',$request->brand)
->where('mobile_devices.ram', '=', $request->ram)
->where('mobile_devices.storage', '=',$request->storage )
->select('products.*')->paginate(15);
below is blade
<div class="product-filter product-filter-bottom filters-panel">
<div class="row">
<div class="col-sm-6 text-left"></div>
<div class="col-sm-6 text-right">{{$products->links()}}</div>
</div>
</div>
working fine in eloquent result but in query result the problem is occuring. The first page is shown but in other pages just blank page appears

Do the properties request->ram and $request->storage carry over to the pagination links? They're probably not if you're not adding them in. See "Appending to Pagination Links" in the docs at https://laravel.com/docs/6.x/pagination#displaying-pagination-results
$products = DB::table(...);
$products->appends([
'ram' => $request->ram,
'storage' => $request->storage,
'brand_id' => $request->brand_id,
'brand' => $request->brand
]);
See also How to automatically append query string to laravel pagination links?

In your view,use the collection/result like this..
#foreach($products as $product)
{{$product->name}} // whatever you want to display
#endforeach
{{$products->links()}} // use the exact name of the object that you are passed to the view

Related

Laravel pagination on each side not working properly

In my Laravel (5.7) controller, I have set pagination + 'on each side navigation' to 2 items. However, this is not working on my view. I'm getting much more items than 2, which causes my window to break out on small mobile devices.
What can be the cause of this and how can I fix it? I mean, I can get it fixed with CSS, but I would like to get it fixed the proper way.
My code in the controller:
public function index(Request $request)
{
$type = 'all';
if ($request->has('type')) {
if ($request->type == 'all') {
$materials = Material::paginate(10)->onEachSide(2);
} else {
$type = $request->type;
$materials = Material::where('type', $type)->paginate(10)->onEachSide(2);
}
} else {
$materials = Material::paginate(10)->onEachSide(2);
}
$stock = array(
'enkelzitKajaks' => Material::where('type', 'Enkelzitkajak')->count(),
'dubbelzitKajaks' => Material::where('type', 'Dubbelzitkajak')->count(),
'canadeseKanos' => Material::where('type', 'Canadese kano')->count(),
'langePeddels' => Material::where('type', 'Lange peddel')->count(),
'kortePeddels' => Material::where('type', 'Korte peddel')->count(),
'tonnetjes' => Material::where('type', 'Tonnetje')->count(),
'zwemvesten' => Material::where('type', 'Zwemvest')->count()
);
return view('materials.index')->with('materials', $materials)->with('stock', $stock)->with('type', $type);
}
My code in the view:
<section class="pagination">
<div class="container">
<div class="row">
<div class="col-12">
{{ $materials->links() }}
</div>
</div>
<hr>
</div>
</section>
A screenshot of my view on small devices:
First of all The laravel pagination onEachSide(x) has leading and tailing parts besides the middle section. Leading two pages and tailing two pages.
You are trying with onEachSide(2) and on the 6th page. So now we try to look at the logic in pagination.
In laravel when using onEachSide(2) it will show pagination like this
leadingTwoPages
currentPage - 2
currentPage
currentPage +2
tailingTwoPages
1,2
4,5
6
7,8
22,23
Then think about the first part of pagination it needs to show the 1st page to the 8th page without the 3rd page.
Instead of page number three, it needs to be a show button with dots.
Then instead of showing a button with dots for page number three, it will show the original 3rd-page number.
After the 6th page the laravel pagination onEachSide(2) will work fine
You can try class="pagination pagination-sm" for mobile device
It's because of a bug in Laravel 5.* versions. If you don't want to upgrade your app, you should manually change some codes in:
vendor/laravel/framework/src/illuminate/Pagination/UrlWindow.php
as mentioned and discussed in below link with Taylor Otwell.
Disccus about on each side bug in Laravel 5.*
You should use onEachSide this in blade.
Remove the onEachSide from the controllers. Using onEachSide in controllers will be helpful when you are creating APIs. Instead use onEachSide in blade file.
<section class="pagination">
<div class="container">
<div class="row">
<div class="col-12">
{{ $materials->onEachSide(1)->links() }}
</div>
</div>
<hr>
</div>
</section>
Use can manage the link window by changing the parameter in onEachSide
https://laravel.com/docs/8.x/pagination#adjusting-the-pagination-link-window

Getting id value from url in controller and displaying values associated laravel

I'm trying to create a ticket management system with laravel jetstream and livewire. In the user page there's a table with all tickets that the user created. When the user clicks on the button to open one specific ticket, it should pass the id of the ticket and redirect to another page where it receives the data of that ticket he clicked, like title, message, etc..
The id is passed through the url, but my main problem is that whenever I try to display that data in the view, nothing shows, no errors either. I think that something might be wrong with my controller.
Here's my route:
Route::get('tickets.answers/{id}', [TicketsController::class, 'answers']);
The button to redirect to that specific ticket:
<a href="{{ url('tickets.answers' . '/'. $ticket->id ) }}" > <x-jet-secondary-button >
See Answer
</x-jet-secondary-button></a>
AnswersController:
public function render(Request $request)
{
$tickets = Ticket::where('id', $request->url('id'));
return view('livewire.tickets.answers', [
'tickets' => $tickets,
]);
}
And how I'm trying to display in my blade:
#foreach($tickets as $key => $ticket)
<!-- This example requires Tailwind CSS v2.0+ -->
<div class="bg-white shadow overflow-hidden sm:rounded-lg">
<div class="px-4 py-5 sm:px-6">
<h3 class="text-lg leading-6 font-medium text-gray-900">
Ticket nº {{$ticket->id}} - {{$ticket->title}}
</h3>
</div>
</div>
#endforeach
In your TicketsController you can fetch the id like this
public function answer(Request $request, int $id)
{
// Use the find() method, instead of where(), when searching for the primary key
$tickets = Ticket::find($id);
// .. more
}
In your routes files you specify an answer method, so use this in your TicketsController.
// See how to name a route
Route::get('tickets.answers/{id}', [TicketsController::class, 'answers'])->name('tickets.answers');
Then use the named route in your view like this:
<a href="{{ route('tickets.answers', ['id' => $ticket->id]) }}">
You can see a similar example in the Laravel docs.

How to display data value according to dropdown in laravel?

I have a table in my database which has a field lis_type and the field has 2 values: sale and rent, and I am calling data on my view page. Let's suppose I click on the Sale page, there only sale similar listing should be displayed. If I click on Rent then similar listing should be shown for rent. However, right now both listings are coming together, Please let me guide where I am making a mistake.
Controller
public function listingshownow(Request $r, $slug)
{
$listview = Listing::where('slug', $slug)->first();
$products = Listing::where('propId', $listview->propId)
->where(function ($query) {
$query->where('lis_type', '=', 'sale')->orWhere('lis_type', '=', 'rent');
})->get();
return view('listings-view', compact('products'));
}
View for Similar Listings...
#foreach($products as $prod)
#if($prod->lis_type === 'sale')
<div class="row featured portfolio-items">
<div class="col-lg-7 col-md-12 homes-content pb-0 mb-44">
<ul class="homes-list clearfix">
<li>
<i class="fa fa-bed" aria-hidden="true"></i>
<span>{{$prod->ls_fs}}</span>
</li>
<li>
<i class="fa fa-bath" aria-hidden="true"></i>
<span>{{$prod->bathroom}} Bathroom</span>
</li>
</ul>
</div>
</div>
#endif
#endforeach
You need to pass a variable to your controller to indicate what kind of page you are viewing, so you can use that in your query/filter.
For example, let's say your sales page URL looks like http://example.com/listings/sales. Then you could set up a route like:
Route::get('listings/{type}', 'ListingsController#show');
Now your ListingsController could have a method like:
// The $type parameter will be what was matched in the route
public function show($type) {
$listings = Listings::where('lis_type', $type)->get();
return view('listings-view', ['listings' => $listings]);
}
You might want to check that $type only matches the values you expect. You could either do that in the controller, eg:
// At the top of show()
if ($type !== 'sales' && $type !== 'rent') {
abort(404);
}
Or you could restrict it in your route, by specifying that the {type} there has to match some pattern:
Route::get('listings/{type}', 'ListingsController#show')->where('type', 'sales|rent');
All of this is covered in the Laravel routing docs, I suggest reading them, and better yet, take some minutes and browse all the docs! 30min skimming will give you a broad idea of how things work, and the knowledge of where to look and read more when you need a question answered.

Laravel custom validation message for multiple fields with the same name

I have the following validation in the controller's action:
foreach ($request['qtys'] as $key => $val){
if (!$this->_validateMinQty($key, $job, $val)){
$customerTitle = $job->customers()->where('customer_id',$key)->first()->title;
return redirect()->back()->withErrors(['qtys' => __('The qty of the customer :customerTitle is less than allowed qty',['customerTitle' => $customerTitle])]);
}
}
This check multiple form's input named qtys in the view:
#foreach($job->customers as $customer)
<div class="form-group {{$errors->first('qtys has-error')}}">
{!! Form::label('qtys-'.$customer->id, __('Qty').' '.$customer->title) !!}
<div class="row">
<div class="col-md-9">
{!! Form::text('qtys['.$customer->id.']',$customer->pivot->e_production,['class' =>'form-control qtys', "data-sumequal"=>"qty",'required' => 'required','title' => $customer->pivot->aid,'id' => 'qtys-'.$customer->id]) !!}
<div class="help-block with-errors"></div>
#php ($eleE = $errors->first('qtys'))
#include('layouts.form-ele-error')
</div>
<div class="col-md-3">
<i class="fox-add"></i>{{__('Add Storage')}}
</div>
</div>
</div>
#endforeach
The above code works, but with the following limitation:
The error message is rendered under every input named qtys[x] where x is an integer and the first input only Testana has the invalid qty, like the following screen shot:
In the controller's action return message, I have tried to use indexed name for the input like the following:
return redirect()->back()->withErrors(['qtys.10' => ....
However, it prevents rendering the error message under any qtys field. Is there any solution?
The solution that I have found starts from the definition of first method found in the view :
#php ($eleE = $errors->first('qtys'))
This, in my code, should be changed to:
#php ($eleE = $errors->first('qtys.'.$customer->id))
Because the multiple fields have gotten keys equals to the customer id. This is a technique I usually use, when I want to send double piece of data in single post or in single form element.
Then in the controller, I keep the first try,
return redirect()->back()->withErrors(['qtys.'.$key => __('The qty of the customer :customerTitle is less than allowed qty',['customerTitle' => $customerTitle])]);
Where $key is an integer.

Pagination is not showing

I'm trying to get pagination into my view. I don't know where is the problem, the code doesn't show any errors.
Here is my controller function
public function apakskategorijas($id)
{
$apakskat = apakskategorijas::with('prece')->where('id',$id)->paginate(2);
return view ('kategorijas.apakskategorijas',compact('apakskat'));
}
View
#section('content')
#foreach($apakskat as $apk)
#foreach($apk->prece as $prec)
<div class="col-md-4 kat">
<a href="{{ url('kategorija/apakskategorija/preces/'.$prec->id) }}">
<div>
<img src="{{ URL::to($prec->path) }}">
</div>
<div class="nos">
<p>{{$prec->nosaukums}}</p>
</div></a>
<div class="price-box-new discount">
<div class="label">Cena</div>
<div class="price">{{ $prec->cena }} €</div>
</div>
<div><span>Ielikt grozā</span></div>
</div>
#endforeach
#endforeach
<center>{{$apakskat->links()}}</center> <--pagination
#endsection
dd($apakskat)
UPDATE
when i changed code in my controller to $apakskat = apakskategorijas::paginate(1); then it showed me pagination, but this doesn't work for me since i need to display items in each subcategory, with this code it just displays every item i have,it doesn't filter which subcategory is selected.
This is why i need this $apakskat = apakskategorijas::with('prece')->where('id',$id)->paginate(1); with is a function that i call which creates a relation between tables, so that it would display every item with its related subcategory.
That's the behavior of paginator in current Laravel version. When you have just one page, pagination links are not displayed.
To test this, just change the code to something like this to get more pages:
$apakskat = apakskategorijas::paginate(1);
If you want to show the first page if there is only one page, you need to customize pagination views. Just publish pagination views and remove this #if/#endif pair from the default.blade.php but keep the rest of the code as is:
#if ($paginator->hasPages())
....
#endif

Resources