Pagination with Laravel Blade - php

I'm trying to return data with a pagination. When I'm returning the data as paginate() I receive an error: htmlspecialchars() expects parameter 1 to be string, array given
My controller:
$tickets = Ticket::where('company_id', Auth::user()->company_id)->paginate(3);
Blade:
<table class="bg-white overflow-hidden table-auto w-full flex-row flex-no-wrap whitespace-nowrap">
<tr>
<th></th>
<th class="bg-white px-4 py-2">Updated at</th>
<th class="bg-white px-4 py-2">Case Title</th>
<th class="bg-white px-4 py-2">Manager</th>
<th class="bg-white px-4 py-2">Case ID</th>
<th class="bg-white px-4 py-2">Remaining</th>
<th class="bg-white px-4 py-2">Status</th>
</tr>
#foreach($tickets as $ticket)
<tr class="bg-gray-100 text-center">
<td class="px-2"><span class="text-blue-900 font-bold text-xs">
#if($ticket->isNew($ticket->created_at))
New
#endif
</span></td>
<td class="px-4">{{ $ticket->updated_at }}</td>
<td class="px-4 py-4">{{ $ticket->title }}</td>
<td class="px-4 py-4">{{ $ticket->getAdmin->first_name }} {{ $ticket->getAdmin->last_name }}</td>
<td class="px-4 py-4">{{ $ticket->id }}</td>
<td class="px-4 py-4">
#php
$dueDate = \Carbon\Carbon::parse($ticket->end_date);
#endphp
#if($dueDate->isPast())
<span class="text-red-600">Overdue</span>
#else
{{ $ticket->remaining_date() }} Days
#endif
</td>
<td class="px-4 py-4">
#if($ticket->status == 1)
<span class="bg-yellow-500 font-semibold text-white p-2 rounded">Active</span>
#endif
#if($ticket->status == 2)
<span class="bg-blue-500 font-semibold text-white p-2 rounded">Closed</span>
#endif
#if($ticket->status == 3)
<span class="bg-red-800 font-semibold text-white p-2 rounded">Late</span>
#endif
</td>
</td>
</tr>
#endforeach
</table>
{{!! $tickets->links() !!}}
I don't get it why I receive the error and have tried to Google around it. Why is the error appear and what's the solution?

Update your version of Laravel. This was a breaking bug for 8.78. They tried changing Pagination Navigation for screen readers, but it broke certain translation settings, so it was reverted back. The details are at https://github.com/laravel/framework/pull/39928
#taylorotwell #xanderificnl This actually introduces a bug that breaks Tailwind pagination out of the box, and it should ideally be reverted.
When attempting to use Tailwind pagination, I'm seeing the following: htmlspecialchars(): Argument #1 ($string) must be of type string, array given (View: /var/www/html/vendor/laravel/framework/src/Illuminate/Pagination/resources/views/tailwind.blade.php)
The line causing the issue:
<nav role="navigation" aria-label="{{ __('Pagination') }}" class="flex items-center justify-between">
This is due to Laravel shipping with a resources/lang/en/pagination.php file by default. This PR causes the array returned by the pagination language file to be passed into the __() method, which results in the parsing exception.

Related

Route [auth.register] not defined

So my problem is that I am getting this error and I have no idea what it means....
Symfony \ Component \ Routing \ Exception \ RouteNotFoundException
Route [auth.register] not defined.
/vendor/laravel/framework/src/Illuminate/Routing/UrlGenerator.php&line=467
public function route($name, $parameters = [], $absolute = true)
{
if (! is_null($route = $this->routes->getByName($name))) {
return $this->toRoute($route, $parameters, $absolute);
}
throw new RouteNotFoundException("Route [{$name}] not defined."); // <= Line 467
}
I am thinking it's probably because my naming is wrong in web.php...
<?php
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Session;
use App\Http\Controllers\ProgramController;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
return view('welcome');
});
Route::get('/index', function () {
return view('index');
});
Route::middleware(['auth:sanctum', config('jetstream.auth_session'), 'verified'])->group(function () {
Route::get('/dashboard', function () {
return view('dashboard');
})->name('dashboard');
});
Route::group(['middleware' => 'auth'], function () {
Route::resource('program', \App\Http\Controllers\ProgramController::class);
Route::resource('manager', \App\Http\Controllers\ManagerController::class);
});
I think maybe it's because since I named it middleware and it's pointing to auth maybe that's the reason I got that error. But I wanted to at least show all the user. I would be very grateful if anyone can help.
So apparently I got forgot I wrote the code wrong and one of the route is pointing at auth.register when it supposed to lead to manager.create in the manager/index.blade.php
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Management') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-6xl mx-auto py-10 sm:px-6 lg:px-8">
<div class="block mb-8">
Add User
</div>
<div class="flex flex-col">
<div class="-my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
<div class="py-2 align-middle inline-block min-w-full sm:px-6 lg:px-8">
<div class="shadow overflow-hidden border-b border-gray-200 sm:rounded-lg">
<table class="min-w-full divide-y divide-gray-200 w-full">
<thead>
<tr>
<th scope="col" width="50" class="px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
ID
</th>
<th scope="col" class="px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Name
</th>
<th scope="col" class="px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Email
</th>
<th scope="col" class="px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Email Verified At
</th>
<th scope="col" class="px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
Roles
</th>
<th scope="col" width="200" class="px-6 py-3 bg-gray-50">
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
#foreach ($manager as $user)
<tr>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
{{ $user->id }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
{{ $user->name }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
{{ $user->email }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
{{ $user->email_verified_at }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
#foreach ($user->roles as $role)
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">
{{ $role->title }}
</span>
#endforeach
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
View
Edit
<form class="inline-block" action="{{ route('manager.destroy', $user->id) }}" method="POST" onsubmit="return confirm('Are you sure?');">
<input type="hidden" name="_method" value="DELETE">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="submit" class="text-red-600 hover:text-red-900 mb-2 mr-2" value="Delete">
</form>
</td>
</tr>
#endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</x-app-layout>
So in the end I was being weird. So if you guys have any problem don't panic like me just read the code again you might have missed something.

Error "Trying to get non-object property" after calling a livewire function

I'm using livewire to call a function that turns the user's role into "writer", the function in the livewire class is as follows :
class User extends Component
{
public $users;
public function turnWriter($id){
DB::table('users')->where('id', $id)->update(['role' => 'writer']);
}
public function render()
{
return view('livewire.user');
}
}
calling the function on the blade template on the button inside the if statement at the end:
<thead class="border-b bg-laravel">
<tr>
<th scope="col" class="text-sm font-medium text-black px-6 py-4">
Username
</th>
<th scope="col" class="text-sm font-medium text-black px-6 py-4">
Email
</th>
<th scope="col" class="text-sm font-medium text-black px-6 py-4">
Verified At
</th>
<th scope="col" class="text-sm font-medium text-black px-6 py-4">
Actions
</th>
<th scope="col" class="text-sm font-medium text-black px-6 py-4">
</th>
</tr>
</thead class="border-b">
<tbody>
#foreach ($users as $user)
<tr class="bg-white border-b">
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
{{$user->name}}
</td>
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
{{$user->email}}
</td>
#if(empty($user->email_verified_at))
<td class="text-sm text-red-500 px-6 py-4 whitespace-nowrap">
Not Verified yet
#else
<td class="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
{{$user->email_verified_at}}
#endif
</td>
<td class="text-red-500 font-light px-6 py-4 hover:bg-red-400 hover:text-white">
Block
</td>
#if($user->role == 'user')
<td>
<div>
<button wire:click="turnWriter({{ $user->id }})" class="text-white bg-teal-500 font-light px-6 py-4 hover:bg-teal-800">
Make Writer
</button>
</div>
</td>
#else
<td class="text-white bg-emerald-600 font-light px-6 py-4 hover:bg-emerald-900">
Remove Writer role
</td>
#endif
</tr class="bg-white border-b">
#endforeach
</tbody>
</table>
the controller function that returns the blade view:
public function dashboard(){
$users = DB::table('users')->where('role', 'user')->Orwhere('role', 'writer')->get();
//dd($users);
return view('users.dashboard',[
'users' => $users,
]);
}
The issue is, when clicking the button, the user's role does get changed to "writer" in the database, the problem comes afterwards, the view can't read the value or the property of $user for some reason and the following error pops up, the function however works just fine:
Livewire does not like stdClass variables. It only supports the types mentioned here. When you use a DB::get(), you get a collection of stdClass, and upon rehydrating the component (as what happens when you add a role to the user), it will convert all of the data to arrays. So, either always cast toArray() so you have an expected result set (and then don't use ->name, but ['name']), or use model collections.
I'd like to add that it's best practice to keep variables inside Livewire components, instead of having them in the main blade. If you don't need the $users variable in your dashboard.blade, then I highly suggest moving it to your component (in the mount method, for example)
I haven't used livewire but don't you think you should pass an argument to view? The $users variable is null in your case if you don't pass it.
public function render()
{
return view('livewire.user', [
'users' => User::all(), //or User::where('role', 'writer')->get(); depending on your logic
]);
}

Laravel LiveWire Pagination issue

I am new to LiveWire and trying to build simple app with Laravel , jetstream and livewire
My application get data from DB and show in Table with Pagination.
every thing is working fine but issue is when i click on any page I got URI '?page=2'
I dont want to see this URI in Url
my blade is also simple as bellow
<x-app-layout>
<x-slot name="header">
</x-slot>
<div class="py-2">
<div class="mx-auto sm:px-2 lg:px-2">
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
<div class="flex flex-wrap">
<livewire:item />
</div>
</div>
</div>
</div>
</x-app-layout>
and livewire:item
<table class="table-auto w-full">
<thead>
<tr>
<th class="px-4 py-2">
<div class="flex items-center">
<button>Image</button>
</div>
</th>
<th class="px-4 py-2">
<div class="flex items-center">
<button wire:click="sortBy('sku')">SKU</button>
<x-sort-icon sortField="sku" :sort-by="$sortBy" :sort-asc="$sortAsc" />
</div>
</th>
<th class="px-4 py-2">
<div class="flex items-center">
<button wire:click="sortBy('title')">Title</button>
<x-sort-icon sortField="title" :sort-by="$sortBy" :sort-asc="$sortAsc" />
</div>
</th>
<th class="px-4 py-2">
<div class="flex items-center">
<button wire:click="sortBy('avg_pprice')">Price</button>
<x-sort-icon sortField="avg_pprice" :sort-by="$sortBy" :sort-asc="$sortAsc" />
</div>
</th>
<th class="px-4 py-2">
<div class="flex items-center">
<button wire:click="sortBy('stock')">Stock</button>
<x-sort-icon sortField="stock" :sort-by="$sortBy" :sort-asc="$sortAsc" />
</div>
</th>
<th class="px-4 py-2">
<div class="flex items-center">
<button wire:click="sortBy('selling_price')">Sale Price</button>
<x-sort-icon sortField="selling_price" :sort-by="$sortBy" :sort-asc="$sortAsc" />
</div>
</th>
<th class="px-4 py-2">
Actions
</th>
</tr>
</thead>
<tbody>
#foreach($items as $item)
<tr>
<td class="border px-4 py-2"><img class="w-20" src='{{ $item->image}}'></td>
<td class="border px-4 py-2">{{ $item->title}}</td>
<td class="border px-4 py-2">{{ number_format($item->price, 2)}}</td>
</tr>
#endforeach
</tbody>
</table>
<div class="mt-4">
{{ $items->links() }}
</div>
Also livewire controller is
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\item;
use Livewire\WithPagination;
class Items extends Component
{
use WithPagination;
public $perPage = 10;
public function render()
{
$items = Item::all();
$items = $items->paginate($this->perPage);
return view('livewire.items', [
'items' => $items,
]);
}
}
It worked as bellow Thanks to #Remul
use Livewire\Component;
use Livewire\WithPagination;
class ContactsTable extends Component
{
use WithPagination;
protected $paginationTheme = 'bootstrap';
public function getQueryString()
{
return [];
}
}
You should have only one root item in your Livewire view livewire:item. Move the
<div class="mt-4">
{{ $items->links() }}
</div>
either within the table tag or create a big div around everything.
<div>
<table>
// table stuff
</table>
<div class="mt-4">
{{ $items->links() }}
</div>
</div>
The ?page=2 for the second page is always appended, this is a correct behaviour. Your table should updated accordingly to the page selected.
In my case, i use and define bootstrap theme on the same links.
$users->links('pagination::bootstrap-4')
but, after check this question, i try:
protected $paginationTheme = 'bootstrap';
That fix my error with the pagination links after type string to search.

Getting an error when displaying the `result` instead of `id` using eloquent relationship, incase the field is optional, and left blank - Laravel

I'm using eloquent relationship to display the sub_category_name from the other table instead of sub_category_id. When I am entering only the category_id and leaving the sub_category_id blank i.e. null, I am unable to display the name of sub_category_id as it is undefined and it throws the error Trying to get property 'sub_category_name' of non-object. How can I avoid this error and display the value as blank instead of finding the sub_category_name.
Here is the code for the model in which the relationship is defined and the source code in which it is retrieving the sub_category_name of the sub_category_id present, and display the name instead of the id.
Model
class MenuItem extends Model
{
use HasFactory;
protected $table = "menu_items";
protected $fillable = ['category_id','sub_category_id', 'item_name', 'item_description'];
public function SubCategories() {
return $this->belongsTo(SubCategory::class, 'sub_category_id');
}
}
Livewire Component
<tbody>
#foreach($menuitemlist as $key=>$menuitem)
<tr style="background-color: {{ $key % 2 == 0 ? '#fdfdfd': '#f5f5f5' }};">
<td class="px-4 py-2">{{ $menuitemlist->firstitem() + $key }}</td>
<td class="px-4 py-2">{{ $menuitem->category_id }}</td>
<!---Here Is The Code Due To Which It's Throwing An Error When `sub_category_id` Is Null--->
<td class="px-4 py-2">{{ $menuitem->subcategories->sub_category_name }}</td>
<td class="px-4 py-2">{{ $menuitem->item_name }}</td>
<td class="px-4 py-2">{{ $menuitem->item_description }}</td>
<td class="px-4 py-2">
<button wire:click="edit({{ $menuitem->id }})" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-1 px-4 rounded">
Edit
</button>
<button wire:click="delete({{ $menuitem->id }})" class="bg-red-500 hover:bg-red-700 text-white font-bold py-1 px-4 rounded">
Delete
</button>
</td>
</tr>
#endforeach
</tbody>

Laravel Livewire Pagination links not working

I create livewire component WithPagination
Links render correct, but even wire:click="gotoPage(2)" not working properly
/** app/Http/Livewire/Project/Index.php **/
namespace App\Http\Livewire\Project;
use App\Models\Project;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
use Livewire\WithPagination;
class Index extends Component
{
use WithPagination;
public function render()
{
return view('livewire.project.index', [
'projects' => Project::where('owner_id', Auth::id())->paginate(10)
]);
}
}
and view
resources/views/livewire/project/index.blade.php
#forelse($projects as $project)
#if($loop->first)
<table class="min-w-full">
<thead>
<tr>
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">ID</th>
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">Title</th>
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">Description</th>
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50 text-left text-xs leading-4 font-medium text-gray-500 uppercase tracking-wider">Owner</th>
<th class="px-6 py-3 border-b border-gray-200 bg-gray-50"></th>
</tr>
</thead>
<tbody class="bg-white">
#endif
<tr>
<td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 text-sm leading-5 text-gray-500">
{{ $project->id }}
</td>
<td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 text-sm leading-5 text-gray-500">
{{ $project->title }}
</td>
<td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200 text-sm leading-5 text-gray-500">
{{ $project->description }}
</td>
<td class="px-6 py-4 whitespace-no-wrap border-b border-gray-200">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10">
<img class="h-10 w-10 rounded-full" src="https://ui-avatars.com/api/?name={{ $project->owner->name }}&color=7F9CF5&background=EBF4FF" alt="" />
</div>
<div class="ml-4">
<div class="text-sm leading-5 font-medium text-gray-900">{{ $project->owner->name }}</div>
<div class="text-sm leading-5 text-gray-500">{{ $project->owner->email }}</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-no-wrap text-right border-b border-gray-200 text-sm leading-5 font-medium">
{{__('View')}}
</td>
</tr>
#if($loop->last)
</tbody>
</table>
{{ $projects->links() }}
#endif
#empty
<h3>No projects yet.</h3>
#endforelse
Video:
https://monosnap.com/file/MO59IoLOCoc93tAbU7ET5IlVAVIHWN
In other components events like wire:submit.prevent="createProject" or wire:click="editProject({{ $project->id }})" working correct
Stack:
PHP 7.4
Laravel 8
Livewire 2
Chrome 85.0.4183.102
I had the same problem and i solved it just by wrapping all the content of the view in a single div, like this.
<div> All your content </div>
Livewire Documentation says:
"Let's say you have a show-posts component, but you want to limit the results to 10 posts per page.
You can paginate the results by using the WithPagination trait provided by Livewire."
Component Controller: App\Http\Livewire\PathToYourComponent\Component:
use Livewire\WithPagination;
class ShowPosts extends Component
{
use WithPagination;
public function render()
{
return view('livewire.show-posts', [
'posts' => Post::paginate(10),
]);
}
}
Component View: resources\views\livewire\path-to-your-component\component-view:
<div>
#foreach ($posts as $post)
...
#endforeach
{{ $posts->links() }}
</div>
*Livewire components MUST have a SINGLE ROOT element
Your Laravel Blade result:
<html>
<head>
...
#livewireStyles
...
</head>
<body>
Your html body here
...
#livewire('your-component')
...
#livewireScripts
</body>
</html>
Hope this will help other people
Ref: Livewire Pagination
you must have a single html container.
You just should all your blade content inside tags.. like this
<div> ----> this one
#section("header")
#include("layouts.v1.app_admin_header")
#include("partials.v1.title",[
"first_title"=>"Listado",
"second_title"=>"de equipos"
])
#endsection
#include("partials.v1.table_nav",
["nav_options"=>[
["button_align"=>"right",
"click_action"=>"",
"button_content"=>"Crear nuevo",
"icon"=>"fa-solid fa-plus",
"target_route"=>"administrar.equipos.agregar",
],
]
])
</div> ----> this one
you can have anything, always inside div tags.
In that way livewire has one root component and all works perfectly
you need to Add first
1- in your controller after {use WithPagination}
protected $paginationTheme = 'bootstrap';
2- in your view
$users->links('pagination::bootstrap-4')

Categories