Laravel pagination on each side not working properly - laravel

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

Related

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.

property does not refresh in the internal components of Livewire

Take a look at the following examples:
showPost.blade.php:
<div>
<livewire:content-box :content="$post"/>
<button wire:click="nextPost" >Next Post >></button>
</div>
and
content-box.blade.php :
<div>
<h1>{{ $content->title }}</h1>
<p>{{ $content->content }}</p>
</div>
So far, it is completely clear what is going to happen ...: First, the information of the content to be viewed is received through showPost and passed to the contentBox, and everything is OK ..
Well now I want to get the information of the next content via the account through the button I put and calling the nextPost method:
class ShowPost extends Component
{
public Post $post;
public function render()
{
return view('livewire.show-post');
}
public function nextPost()
{
$id = $this->post->id;
$nextPost = Post::where('id', '>', $id)->first();
$this->post = $nextPost;
}
...
But nothing happens and the contentBox component has no reaction .... Has anyone had this problem ???!
I'm not sure livewire works well with nested components. could use the pagination instead. The livewire docs suggest you should not use them for little snippets or use blade components for that kind of nesting.
You can achieve what you're doing at the moment with some simple pagination.
<?php
namespace App\Http\Livewire;
use App\Models\User;
use Livewire\Component;
use Livewire\WithPagination;
class SomeContent extends Component
{
use WithPagination;
public function render()
{
// Using simplePaginate(1) instead of paginate(1).
// simplePaginate only shows "<- Previous" and "Next ->" links
// paginate shows those 2 buttons but also page numbers which you don't seem to want.
return view('livewire.some-content', [
'users' => User::simplePaginate(1),
]);
}
}
<div>
{{-- This might look wrong, but essentially it's looping through an array of length 1 because we're paginating --}}
#foreach ($users as $user)
<h1>{{ $user->name }}</h1>
<h2>{{ $user->email }}</h2>
#endforeach
{!! $users->links() !!}
</div>
EDIT
I can confirm blade components work.
Here, nextUser is the same implementation you gave.
public function nextUser()
{
$id = $this->user->id;
$nextUser = User::where('id', '>', $id)->first();
$this->user = $nextUser;
}
<div class="container">
<div class="content">
{{-- These two have the exact same template --}}
<livewire:child :user="$user" />{{-- Doesn't update when clicking Next --}}
<x-blade-child :user="$user" />{{-- Updates when clicking Next --}}
</div>
<div>
<button wire:click="nextUser">Next</button>
</div>
</div>
When clicking nextUser, the blade component updates but the livewire one doesn't.
Livewire doesn't like nested components. In your case, we can use basic blade component:
<div>
<x-content-box :content="$post"/>
<button wire:click="nextPost" >Next Post >></button>
</div>
And then:
Move content-box.blade.php to resources/views/components/
Remove component_name.php file in app/Http/Livewire
Most of the time, we can change 2 nested livewire components to livewire(parent) + basic blade component(child),

blank page in next page in laravel pagination

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

to get data in a modal in Laravel

Is there any way to get the data inside a modal? I know that it is possible to work with this through Jquery, but I would like to know if there is any way to work with Laravel itself. In a view, we can do this:
return view ('admin/users/index', ['datas1' => $ datas1, 'datas2' => $datas2];
but for a modal, is it possible to do something like this? to send my data through the controller and within my modal I check if this data are coming empty or filled, as this answer I just want to show different things, like this:
$dep = User::query()->where('dep_link', $id)->get();
 return['status' => 'success', 'dep' => $dep];
only my validation in the modal:
<div class="row" style="padding: 28px 20px;">
<div class="col-12">
#if(empty($dep))
<div class="position-relative">
<label for="rg_titular">Selecione o RG do titular (.png .jpg .pdf)</label><br>
<input type="file" name="rg_titular" class="file-input"/>
<button type="button" class="file-button">Selecionar arquivo</button>
<span class="text-arquivo">Arquivo selecionado!</span>
</div>
#else
<a href="link" target="_blank">
Visualizar RG do titular
</a>
#endif
</div>
</div>
Is there any way I can get this data inside the modal window and work with them? I just want to check if it's coming empty or not, that's all.
You can write a view composer for the modal blade file.
https://laravel.com/docs/5.8/views#view-composers
In your service provider (app, or a custom one you make)
public function boot()
{
view()->composer('myBladeFileName', function ($view) {
$activeUsers = \App\User::where('active', true)->get();
$view->with(compact('activeUsers'));
});
}

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