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')
Related
Want to ask, why is it that when I input data from a table, only 1 data appears in MySQL from the shared table input?
Here is a picture of the table on the website. And there are 3 student data for input. but later only 1 will appear which is given a red line in the image below, 3 data should appear in mysql.
But after inputting data from the table, only 1 data appears in MySQL, 3 data should appear in MySQL.
Blade
<div class="overflow-x-auto relative shadow-md sm:rounded-lg">
<form method="POST" action="{{route('add.teacher.attendance.detail')}}" enctype="multipart/form-data">
#csrf
<table class="w-full text-sm text-left text-gray-500 dark:text-gray-400">
<thead class="text-xs text-white uppercase bg-[#464867] dark:bg-[#464867]">
<tr>
<th scope="col" class="py-3 px-6">
NISN
</th>
<th scope="col" class="py-3 px-6">
Name
</th>
<th scope="col" class="py-3 px-6">
Attendance
</th>
<th scope="col" class="py-3 px-6">
Note
</th>
</tr>
</thead>
<tbody>
#foreach($dataAttendanceTa as $data)
<tr class="bg-white border-b dark:bg-gray-900 dark:border-gray-700">
<th scope="row" class="py-4 px-6 font-medium text-gray-900 whitespace-nowrap dark:text-white">
{{$data->username}}
<input
type="hidden"
name="id_atte"
id="id_atte"
value="{{$data->id_atte}}"
>
<input
type="hidden"
name="id_student"
id="id_student"
value="{{$data->id}}"
>
</th>
<td class="py-4 px-6 font-medium text-gray-900 whitespace-nowrap dark:text-white">
{{$data->name}}
</td>
<td class="flex py-4 px-6 w-10 font-medium text-gray-900 whitespace-nowrap dark:text-white">
<form class="flex">
<div class="flex items-center mb-4 ml-3">
<input id="present" type="radio" name="id_atte_type" value="2" class="w-4 h-4 border-gray-300 focus:ring-2 focus:ring-blue-300 dark:focus:ring-blue-600 dark:focus:bg-blue-600 dark:bg-gray-700 dark:border-gray-600" checked>
<label for="present" class="block ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">
Present
</label>
</div>
<div class="flex items-center mb-4 ml-3">
<input id="sick" type="radio" name="id_atte_type" value="1" class="w-4 h-4 border-gray-300 focus:ring-2 focus:ring-blue-300 dark:focus:ring-blue-600 dark:focus:bg-blue-600 dark:bg-gray-700 dark:border-gray-600">
<label for="sick" class="block ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">
Sick
</label>
</div>
<div class="flex items-center mb-4 ml-3">
<input id="absent" type="radio" name="id_atte_type" value="3" class="w-4 h-4 border-gray-300 focus:ring-2 focus:ring-blue-300 dark:focus:ring-blue-600 dark:bg-gray-700 dark:border-gray-600">
<label for="absent" class="block ml-2 text-sm font-medium text-gray-900 dark:text-gray-300">
Absent
</label>
</div>
</form>
</td>
<td class="py-4 px-6 font-medium text-gray-900 whitespace-nowrap dark:text-white">
<input
type="text"
name="note"
id="note"
autocomplete="note"
value="{{ old('note') }}"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white"
>
</td>
</tr>
#endforeach
</tbody>
</table>
<input type="submit" class="mt-3 mb-3 focus:outline-none text-white bg-[#464867] hover:bg-[#464867] font-medium rounded-lg text-sm px-5 py-2.5 mb-2 " value="Done" >
</form>
</div>
Controllers
public function ViewAttendance($id){
$dataAttendance = Attendance::findOrFail($id);
$dataAttendanceTa = Attendance::join('subjects', 'attendances.id_subject', '=', 'subjects.id_sub')
->join('class_infos', 'subjects.id_class', '=', 'class_infos.id')
->join('class_details', 'class_infos.id', '=', 'class_details.id_class')
->join('users', 'class_details.id_user', '=', 'users.id')
->where('attendances.id_atte', '=', $id)
->get();
return view('teacher.attendance.data_attendance_detail', compact( 'dataAttendance', 'dataAttendanceTa'));
}
public function AddAttendanceDetail(Request $request) {
$addAttendanceDetail = new AttendanceDetail();
$request->validate([
'id_atte' => ['required'],
'id_student' => ['required'],
'id_atte_type' => ['required'],
]);
$addAttendanceDetail->id_atte = $request->input('id_atte');
$addAttendanceDetail->id_student = $request->input('id_student');
$addAttendanceDetail->id_atte_type = $request->input('id_atte_type');
$addAttendanceDetail->note = $request->input('note');
$addAttendanceDetail->save();
return redirect('teacher/data-attendance');
}
So for Controllers I join with other table data.
Model
class AttendanceDetail extends Model
{
use HasFactory;
protected $primaryKey = 'id_atte_detail';
protected $table = 'attendance_details';
protected $fillable = [
'id_atte_detail',
'id_atte',
'id_student',
'id_atte_type',
'note',
];
}
What is the solution so that when you click the DONE button, all the data in MySQL appears? and is there something wrong in my coding or in mysql?
I'm still new to Laravel but this might be able to help you since, as you press "DONE" you are saving data by multiple student ID's
Instead of doing it once like
$addAttendanceDetail->id_atte = $request->input('id_atte');
$addAttendanceDetail->id_student = $request->input('id_student');
$addAttendanceDetail->id_atte_type = $request->input('id_atte_type');
$addAttendanceDetail->note = $request->input('note');
$addAttendanceDetail->save();
You should use foreach
$data = $request->all();
$finalArray = [];
foreach ($data as $key => $value) {
array_push(
$finalArray,
[
'id_atte' => $value['id_atte'],
'id_student' => $value['id_student'],
'id_atte_type' => $value['id_atte_type'],
'note' => $value['note']
]
);
});
AttendanceDetail::insert($finalArray);
Still, not really sure, but might be helpful
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.
A table row displayed data value instead of the department names. I tried to do some reading at the laravel website and found that this topic is under Eloquent:Relationships and thus have tried to implement it on my models. If I just use {{ $data->department }}, that allows me to retrieve the data but I got the value, an integer that corresponds to the department category on the table. But when I use {{ $data->Department->department }}, it got me an error Undefined property: stdClass::$DepartmentHowever, it seems like it's not working out. I think that I got some gaps in my knowledge. Please help. In a very tight schedule, I need to complete this project by tomorrow.
Data that I want to retrieve
<tbody class="bg-white divide-y divide-gray-200">
#foreach($info as $data)
<tr>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10">
{{ $data -> staff_id }}
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">{{ $data -> name }}</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">{{ $data -> email }}</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{{ $data->Department->department }}
</td>
#endforeach
#if (auth()->user())
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"> View profile </td>
#endif
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"></td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"></td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"></td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"> Edit </td>
</tr>
</tbody>
To use Department, I created a new function and put it on all my 4 models, to see that it may works. But in this case it didn't.
public function Department()
{
return $this->belongsTo(Department::class, 'department');
}
The page of the data that I shown previously is in AdminController and the route is,
Route::get('staffrecord', [AdminController::class, 'index'])->middleware('auth');
$data query in AdminController
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class AdminController extends Controller
{
public function index()
{
$info = DB::table('users')->get();
return view('staffrecord', compact('info'));
}
}
Do I have to create a new model that corresponds to AdminController ? If it is, how should I name it ?
you need to call the relationship with the query:
$info = User::with('department')->get() ;
this should work.
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
]);
}
I am working on a project to get orders from an API and display them in a dashboard with some basic information (my first project). Currently what i am displaying looks like this:
Fields from left to right:
Date, Amount of products in order, price
I'm currently looping through all products in an order and display the amount, therefore it displays "1 15", the same goes for price. I want to add them up instead and just display "16".
I'm trying to create a method to do so but i cant seem to get it working. This is my current code.
HTML
<tr v-for="(order, index) in orders"
v-bind:class="index % 2 === 0 ? 'bg-white' : 'bg-gray-50'">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{{ order.id }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
{{ order.deliveryName }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
{{ order.createdAt }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<span v-for="(product) in order.products">
{{ product.amount }}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<span v-for="(product) in order.products">
{{ product.amount * product.price }}<br>
</span>
</td>
i tried removing the order.products loop and instead do so in a method but i couldn't get it working.
For example (i tried tweaking the method around a bit to no avail)
In HTML:
{{ getOrderAmount(order)}}
In SCRIPT:
getOrderAmount: function (order) {
let amount = 0;
order.forEach(product) in order.products
{
amount += product.amount
}
return amount;
},
How can i go about this. Help is much appreciated!
You could map your orders by summing the product amount/prive using a computed property then use that property inside the template :
computed(){
mappedOrders(){
this.order.map((order)=>{
order.productsAmount=order.products.reduce((acc,curr)=>{
return acc+=curr.amount;
},0)
order.sumPrices=order.products.reduce((acc,curr)=>{
return acc+=curr.amount * curr.price ;
},0)
return order;
})
}
}
in template :
<tr v-for="(order, index) in mappedOrders" ..>
...
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<span >
{{ order.productsAmount}}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
<span >
{{ order.sumPrices}}<br>
</span>
</td>
</tr>