Laravel Livewire strange table rendering behavior - laravel

I have a table component in my page that renders a list of users, and one of the columns in the table is the user's role. when I paginate through the table of users, livewire is randomly inserting a row in the table for the role, like it's somehow getting confused and including the relationship in the loop, instead of just the main model.
This is the result after paginating:
Here's what it's doing to the markup:
It only happens the first time the page is loaded and I click one of the pagination buttons. It will randomly happen on one or more pages as I paginate through the table, but once I reach the end, I can paginate through every page any number of times without seeing it again until I refresh the page.
Here is my User model:
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable, SoftDeletes, CanResetPassword, HasFactory;
protected $with = ['role'];
public function role()
{
return $this->belongsTo(Role::class);
}
}
Here's my Role model:
class Role extends Model
{
use HasFactory, SoftDeletes;
public function user()
{
return $this->hasOne(User::class);
}
}
My Livewire UserListComponent, which is a full-page component:
class UserListComponent extends Component
{
use WithPagination;
public $search;
public $roles;
public $user;
protected $paginationTheme = 'bootstrap';
protected $listeners = ['refreshUsers' => '$refresh'];
public function mount()
{
$this->search = '';
}
public function render()
{
return view('livewire.users.index', [
'users' => User::withTrashed()->search(['first_name', 'last_name'], $this->search)->paginate(5)
]);
}
public function show($id)
{
return redirect()->route('users.edit', ['user' => $id]);
}
}
My blade view:
<x-table search="true">
#slot('head')
<th>ID</th>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
<th>Role</th>
<th>Status</th>
#endslot
#slot('body')
#forelse($users as $user)
<x-table.row id="{{ $user->id }}" includeStatus="true" :status="$user->deleted_at">
<td>{{ $user->id }}</td>
<td>{{ $user->first_name }}</td>
<td>{{ $user->last_name }}</td>
<td>{{ $user->email }}</td>
<td>{{ $user->role->name }}</td>
</x-table.row>
#empty
<x-table.empty-row colSpan="6" />
#endforelse
#endslot
#slot('paginationLinks')
{{ $users->links() }}
#endslot
</x-table>
And here's the table component content:
#props(['search' => false, 'paginationLinks' => false])
<div class="table-responsive">
<div class="d-flex flex-row justify-content-between">
<div class="col-md-3"></div>
<div class="col-md-2">
#if ($search)
<input wire:model="search" placeholder="Search" type="text" class="form-control">
#endif
</div>
</div>
<table class="table">
<thead>
<tr>
{{ $head }}
</tr>
</thead>
<tbody>
{{ $body }}
</tbody>
</table>
<div class="mt-4">
#if ($paginationLinks)
{{ $paginationLinks }}
#endif
</div>
</div>
And the table row component:
#props(['includeStatus' => false, 'status' => false, 'id'])
<tr wire:key="{{ $id }}" wire:loading.class.delay="opacity-50" wire:target="search" wire:click="show({{ $id }})">
{{ $slot }}
#if ($includeStatus)
<td>
#if ($status)
<span class=" ms-2 badge bg-danger">Inactive</span>
#else
<span class="ms-2 badge bg-success">Active</span>
#endif
</td>
#endif
</tr>

Related

How to display data from 2 tables in Laravel?

Restaurant Model
class Restaurant extends Model
{
use HasFactory;
public $timestamps = false;
public function menus(){
return $this->hasMany(Menu::class, 'resto_id');
}
public function restoimages(){
return $this->hasOne(RestoImage::class, 'resto_id');
}
}
RestoImage Model
class RestoImage extends Model
{
use HasFactory;
public $timestamps = false;
protected $fillable = ['image','resto_id'];
public function restaurants(){
return $this->belongsTo(Restaurant::class, 'resto_id');
}
}
View File
<div class="card mb-4">
<div class="card-body">
<table id="datatablesSimple">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Image</th>
<th>Address</th>
<th colspan="2">Operations</th>
</tr>
</thead>
<tbody>
#foreach($data as $item)
<tr>
<td>{{$item->id}}</td>
<td>{{$item->name}}</td>
<td>{{$item->email}}</td>
<td>{{$item->restoimages->image}}</td>
<td>{{$item->address}}</td>
<td><button>EDIT</button></td>
</tr>
#endforeach
</tbody>
</table>
</div>
</div>
RestoController
public function list(){
$data = Restaurant::with('restoimages')->get();
$restoimages = RestoImage::all();
return view('list', compact('data', 'restoimages'));
}
I have 2 tables, one is restaurants and other is resto_images. When an admin inserts new restaurant using a form. Record will be inserted in aboce 2 tables. resto_images table has column resto_id but when I tried to display image from resto_images table, it throws error (Attempt to read property "image" on null). Please correct me if I am wrong. Thanks in advance.
in your view, you can use the optional function of Laravel or check that there is real value in your relationship with a if,
<td>{{ optional($item->restoimages)->image}}</td>
or
<td>{{ $item->restoimages ? $item->restoimages->image : null }}</td>
Dont forget the img tag if you want to show the image and css attribute to resize the image.
If your images are directly in the public folder, then :
<td style="width:150px;height:100px;"> //some style to resize images
#if ($item->restoimages)
<img src="{{ asset($item->restoimages->image) }}" alt="">
#else
<p>no image</p>
#endif
</td>
But if your images are in public/folderName, then :
<td style="width:150px;height:100px;">
#if ($item->restoimages)
<img src="{{ asset('folderName/' . $item->restoimages->image) }}" alt="">
#else
<p>no image</p>
#endif
</td>

Laravel - How to Filter records using dopdown on submit

In my Laravel-5.8 project, I have this codes:
Model:
class HrEmployee extends Model
{
protected $table = 'hr_employees';
protected $primaryKey = 'id';
protected $fillable = [
'id',
'department_id',
'first_name',
'last_name',
];
public function department()
{
return $this->belongsTo('App\Models\Hr\HrDepartment','department_id','id');
}
}
deptfilters in the controller filters the hr_employees table using department_id
Controller:
public function index(Request $request)
{
$employeedatas = HrEmployee::where('status', 1)->get();
$deptfilters = HrDepartment::where('status', 1)->pluck('department_name','id');
return view('hr.employees.index')
->with('deptfilters', $deptfilters)
->with('employeedatas', $employeedatas);
}
view
<div class="container">
<br>
<form action="ViewPages" method="POST" enctype="multipart/form-data">
#csrf
<div class="container">
<div class="row">
<label for="from" class="col-form-label">Department</label>
<div class="col-md-2">
<select id="department" name="department" class="form-control">
<option value="">--- Select department ---</option>
#foreach ($department as $key => $value)
<option value="{{ $key }}" {{ old( 'department')==$ key ? 'selected' : ''}}>{{ $value }}</option>
#endforeach
</select>
</div>
<div class="col-md-4">
<button type="submit" class="btn btn-primary btn-sm" name="search">Search</button>
</div>
</div>
</div>
</form>
<br>
<table class="table table-dark">
<tr>
<th>id</th>
<th>First Name</th>
<th>Last Name</th>
<th>Department</th>
</tr>
#foreach ($employeedatas as $employeedata)
<tr>
<td>{{ $employeedata->id }}</td>
<td>{{ $employeedata->first_name }}</td>
<td>{{ $employeedata->last_name }}</td>
<td>{{ $employeedata->department->department_name }}</td>
</tr>
#endforeach
</table>
</div>
From the code each department has many employees. What I want to achieve is that:
By default, the dropdown should load department where current_year = 1
When the search button is submitted, I want the table to be fields with records based on the department_id in the dropdown.
How do I modify my controller and view code to achieve this?
Thanks
In general you don't need for $table and $id property when you are using Laravel conventions
class HrEmployee extends Model
{
//protected $table = 'hr_employees';//Laravel by default expect table name 'hr_employees'
//protected $primaryKey = 'id';//Laravel by default expect primary_key on table is id column
protected $fillable = [
'id',
'department_id',
'first_name',
'last_name',
];
public function department()
{
//return $this->belongsTo('App\Models\Hr\HrDepartment','department_id','id');
return $this->belongsTo('App\Models\Hr\HrDepartment');//No Need for override foreign key and owner key when you are using laravel conventions
}
}
In Controller
public function index(Request $request)
{
$employees = HrEmployee::where('status', 1);
if($request->input('department_id')){
$employees->where('department_id',$request->input('department_id'))
}
$employees=$employees->get();
$departments = HrDepartment::where('current_year',1)->where('status', 1)->pluck('department_name','id');
return view('hr.employees.index')
->with('departments', $departments)
->with('employees', $employees);
}
In View For filter use GET NOT POST METHOD
<div class="container">
<br>
<form method="get">
<div class="container">
<div class="row">
<label for="from" class="col-form-label">Department</label>
<div class="col-md-2">
<select id="department" name="department_id" class="form-control">
<option value="">--- Select department ---</option>
#foreach ($departments as $id => $name)
<option value="{{ $id }}" {{ request('depratment_id')==$id ? 'selected' : ''}}>{{ $name }}</option>
#endforeach
</select>
</div>
<div class="col-md-4">
<button type="submit" class="btn btn-primary btn-sm" name="search">Search</button>
</div>
</div>
</div>
</form>
<br>
<table class="table table-dark">
<tr>
<th>id</th>
<th>First Name</th>
<th>Last Name</th>
<th>Department</th>
</tr>
#foreach ($employees as $employee)
<tr>
<td>{{ $employee->id }}</td>
<td>{{ $employee->first_name }}</td>
<td>{{ $employee->last_name }}</td>
<td>{{ optional($employee->department)->department_name }}</td>
</tr>
#endforeach
</table>
</div>
You have pass the data using Ajax to the controller based on your filter values you should return the results of the filter without refreshing the page
Refer this
https://www.webslesson.info/2019/07/implement-custom-search-filter-in-laravel-58-datatable-using-ajax.html?m=1
public function index(Request $request)
{
//Build initial query to fetch employee data
$employeeQuery = HrEmployee::query()->where('status', 1);
//If a department has been selected by user
//filter the employee data by the selected department_id
if(!empty($request->department)) {
$employeeQuery->where('department_id', $request->department);
}
//Get the employee data by executing the $employeeQuery
$employeedatas = $employeeQuery->get();
//Get all the departments where current_year = 1
//if current_year is not a column on the departments table
//replace where('current_year', 1) with whereYear('created_at',now()->format('Y'))
//replace 'created_at' with whichever date column you want to compare with current year
$deptfilters = HrDepartment::where('status', 1)
->where('current_year', 1)
->pluck('department_name','id');
return view('hr.employees.index')
->with('deptfilters', $deptfilters)
->with('employeedatas', $employeedatas);
}

Laravel - How to Approve all the posts of a particular Employee

Using Laravel-5.8, I have written a code for post of employees and it is working perfectly:
Controller
public function index()
{
$userEmployee = Auth::user()->employee_id;
$posts = Post::latest()->where('employee_id', $userEmployee)->get();
return view('admin.post.index', compact('posts'));
}
And it generates this view shown below. The view loads all the unapproved posts for a particular employee:
<table class="table table-bordered table-striped table-hover dataTable js-exportable">
<thead>
<tr>
<th>ID</th>
<th>Title</th>
<th>Author</th>
<th><i class="material-icons">visibility</i></th>
<th>Is Approved</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
#foreach($posts as $key=>$post)
<tr>
<td>{{ $key + 1 }}</td>
<td>{{ str_limit($post->title,'10') }}</td>
<td>{{ $post->user->name }}</td>
<td>{{ $post->view_count }}</td>
<td>
#if($post->is_approved == true)
<span class="badge bg-blue">Approved</span>
#else
<span class="badge bg-pink">Pending</span>
#endif
</td>
<td>
#if($post->status == true)
<span class="badge bg-blue">Published</span>
#else
<span class="badge bg-pink">Pending</span>
#endif
</td>
</tr>
#endforeach
</tbody>
<form action="{{route('admin.post.approve', $post->id)}}" method="POST" enctype="multipart/form-data">
#csrf
#method('PUT')
<div>
<button type="submit" class="btn btn-primary"><i class="fas fa-arrow-right"></i> {{ trans('global.submit') }}</button>
</div>
</form>
I want to add a submit button to the view called approve. Once the button is clicked, it checks where is_approved is = 0 for the loaded employee and turns all the is_approved that relates to the employee (the loaded) data to 1.
I have written this function in the same controller, but I see that it will only work for a selected row:
public function approve($id){
$post = Post::find($id);
if ($post->is_approved == false){
$post->is_approved = true;
$post->save();
$post->user->notify(new AuthorPostApprove($post));
Toastr::success('Post Successfully Approved');
}else{
Toastr::info('Post is already Approved');
}
return redirect()->back();
}
and have this route/web.php
Route::get('posts/', 'PostController#index')->name('post.index');
Route::put('/post/{id}/approve', 'PostController#approve')->name('post.approve');
How do I re-write my Controller, view and route to achieve this?
Thank you.
try this:
public function approve($id){
$post = Post::where('employee_id', $id)
->where('is_approved', 0)
->update(['is_approved' => 1]);
if ($post){
$post->user->notify(new AuthorPostApprove($post));
Toastr::success('Post Successfully Approved');
} else {
Toastr::info('Post is already Approved');
}
return redirect()->back();
}
Ok I do something like below
All you need to do is that when user click the button then it should call for a function where that function will update all unapproved posts. So Im implementing it as below.
First I load all the unapproved post of the current logged in user . With just adding extra where clause in to your index function
Controoler for all unapproved posts
public function index()
{ //Fetching all unapproved post and passing it into view
$userEmployee = Auth::user()->employee_id;
$posts = Post::latest()->where('employee_id', $userEmployee)->where('is_approved',0)->get();
return view('admin.post.index', compact('posts'));
}
Defining the route
Define a route like below first and that route will call for the function named as approve_all_posts in PostController .
Route::post('/post/approve_all_posts', 'PostController#approve_all_posts')->name('post.approve.all');
New function for update
Then I make the function approve_all_posts () in PostController
public function approve_all_posts(){
$unapproved_post = Post::where('is_approved',0)->update(['is_approved' => 1]);
return redirect()->back();
}
Update blade file with button
Then in admin/post/index.blade.php
I add a button called approve all posts like below
Approve all unapproved posts

How to get data from a related table in laravel

I am trying to get data of an animal through a relationship with the user table
Here is my controller
<?php
namespace App\Http\Controllers;
use App\Animal;
use App\Clinic;
use App\Role;
use App\Slaughter;
use Illuminate\Foundation\Auth\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class ClinicController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
$farms = User::where('role_id', 3)->get();
$user = Auth::user();
$animal = Animal::all();
return view('clinic.index', compact('user', 'animal', 'farms'));
}
public function show($id)
{
$farm = User::query()->findOrFail($id);
return view('clinic.show', compact('farm'));
}
While getting the user which is Farm in my case, I would like to get the animals the farm admin registered through this relationship
Model
class Clinic extends Model
{
protected $guarded = [];
public function user(){
return $this->belongsTo(User::class);
}
}
From My tinker, the relationship is working perfectly
Here comes my index page
#extends('layouts.app')
#section('content')
<br><br><br><br><br><br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-20">
<div class="card">
<div class="card-header">
<center>
<h1>Clinic Dashboard</h1>
</center>
</div>
<div class="card-body">
#if (session('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
#endif
<center>
<h2>Welcome! <strong>{{ Auth::user()->name }}</strong></h2>
</center>
<hr>
<br>
<div class="container box">
<div class="table-responsive">
<table class="table table-striped table-bordered" style="background: white">
<thead>
<tr>
<th>Farm Id</th>
<th>Farm Name</th>
<th>Action</th>
</tr>
</thead>
#foreach( $farms as $farm)
<tbody>
<tr>
<td>{{ $farm->id }}</td>
<td>{{ $farm->name }}</td>
<td><a href="/clinic/{{ $farm->id }}"><button
class="btn btn-outline-primary">View Farm
Animals</button></a></td>
</tr>
</tbody>
#endforeach
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
#endsection
And my route
Route::get('/clinic/{farm}', 'ClinicController#show');
And finally the show view where I am getting all the errors
#extends('layouts.app')
#section('content')
<br><br><br><br><br><br>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-20">
<div class="card">
<div class="card-header">
<center>
<h1>Farm Dashboard</h1>
</center>
</div>
<div class="card-body">
#if (session('status'))
<div class="alert alert-success" role="alert">
{{ session('status') }}
</div>
#endif
<center>
<h2>Welcome! <strong>{{ Auth::user()->name }}</strong></h2>
</center>
<hr>
<br>
<div class="container box">
<div class="table-responsive">
<table class="table table-striped table-bordered" style="background: white">
<thead>
<tr>
<th>Id</th>
<th>Animal Type</th>
<th>Sex</th>
<th>Farm</th>
<th>Clinic</th>
<th>Vaccination</th>
<th>Nutrition</th>
</tr>
</thead>
#foreach( $farm as $farm)
<tbody>
<tr>
<td>{{ $farm->animals->id }}</td>
<td>{{ $farm->animals->type->category }}</td>
<td>{{ $farm->animals->gender }}</td>
<td>{{ $farm->animals->user->name }}</td>
#if(! $farm->animals->clinic)
<td>N/A</td>
<td>N/A</td>
<td>N/A</td>
<td>
<a href="/clinic/{{ $farm->animals->id }}/create">
<button type="button" class="btn btn-primary">
Attach Clinic Detail
</button>
</a>
</td>
#elseif( $farm->animals->clinic)
<td>{{ $farm->animals->clinic->user->name }}</td>
<td>{{ $farm->animals->clinic->vaccination ?? 'N/A' }}</td>
<td>{{ $farm->animals->clinic->nutrition ?? 'N/A'}}</td>
<td>
<a
href="/clinic/{{ $farm->animals->clinic->id }}/edit">
<button type="button"
class="btn btn-primary">Edit Animal
Clinic details</button>
</a>
</td>
#endif
</tr>
</tbody>
#endforeach
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
#endsection
I hope I have provided all the fields that could be generating errors. Any assist will be kindly taken as it is a very important project for me
The error I am getting is
Trying to get property 'animals' of non-object
this setup allows you to get all the animals of all the users of a specific clinic. I leveraged route/model binding on your show() method too. Whatever ID you pass in the URL it will automatically load the clinic up.
// app/User.php
class User extends Autheticatable
{
public function animals()
{
return $this->hasMany('App\Animal');
}
public function clinic()
{
return $this->belongsTo('App\Clinic');
}
}
// app/Clinic.php
class Clinic extends Model
{
public function users()
{
return $this->hasMany('App\User');
}
}
// app/Animal.php
class Animal extends Model
{
public function user()
{
return $this->belongsTo('App\User');
}
}
class ClinicController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
public function show(Clinic $clinic)
{
return view('clinic.show', compact('clinic'));
}
}
// view
#foreach($clinic->users as $farm)
#foreach($farm->animals as $animal)
{{ $animal->name }} - {{ $animal->weight }} etc...
#endforeach
#endforeach
In your view you have #foreach($farm as $farm)
What you need: #foreach($farms as $farm)
Edit: this only addresses part of the issue, upon closer inspection your relationships are out of whack, I'll see if I can whip something up.
To get the related Animals for the $farm I would go
public function show($id)
{
$farm = User::with(['animals'])->findOrFail($id);
return view('clinic.show', compact('farm'));
}
Then in your blade
#foreach($farm->animals as $animal)
{{ $animal->id }}
#endforeach
This is assuming you have your animal relation set in your user model of course which would be something like
public function animals()
{
return $this->hasMany('App\Animals')
}
(All untested)

I am trying to retrieve data and display it in a page in laravel 5.3

Following is my show page code to display the data:
#extends('layouts.app')
#section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div
class="panel-heading">subnet_behind_clients
</div>
<div class="panel-body">
<form class="form-horizontal" role="form" method="GET" action="{{ url('/subnet_behind_clients') }}">
{{ csrf_field() }}
<table class="table table-hover">
<thead>
<tr>
<th></th>
<th>client_id</th>
<th>ip_address</th>
<th>netmask</th>
</tr>
</thead>
<tbody>
#foreach($clients as $client)
<tr>
<td>{{ ++$i }}</td>
<td>{{ $client->ip_address }}</td>
<td>{{ $client->netmask }}</td>
<td>
<button type = "button" class = "btn btn-danger " data-target = "del/{{$client->id}}">Delete</button>
</td>
/tr>
#endforeach
</tbody>
</table>
<div class="panel-body">
Home
</div>
</div>
</div>
</div>
</div>
</div>
#endsection
and following is my controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Subnet_behind_client;
use DateTime;
class Subnet_Behind_ClientController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index(Request $request)
{
/* $datas = Subnet_behind_client::all();
$data = $datas->first();*/
$data = Subnet_behind_client::first();
return view('subnet_behind_clients',compact('data'));
}
public function create(Request $request)
{
$data = new Subnet_behind_client;
return view('subnet_behind_clients1',compact('data'));
Subnet_behind_client::create([
//'client_id' => $request->input('1'),
'ip_address' => $request->input('ip_address'),
'netmask' => $request->input('netmask'),
]);
}
public function store(Request $request)
{
$datas = Subnet_behind_client::all();
$data = new Subnet_behind_client;
$data->client_id = '1';
$data->ip_address = $request->ip_address;
$data->netmask = $request->netmask;
$data->save();
return back();
}
public function show(Request $request)
{
$clients = Subnet_behind_client::all();
return view('view2',compact('clients'));
}
public function destroy($id)
{
$clients = Subnet_behind_client::findOrFail( $id );
$clients->delete();
return view('view2',compact('clients'));
}
}
plz let me know what is wrong for the code in foreach
the first part is the view page
and the second page is for the controller part
I made edited my earlier post. Plz take a look and let me know.
You controller should look like this:
use App\Subnet_behind_clients;
public function show(Request $request)
{
$clients = Subnet_behind_clients::all();
return view('view2', compact('clients '));
}
And view:
#foreach($clients as $client)
....
#endforeach
Never use Eloquent or Query Builder in views.
if you got Class 'App\Http\Controllers\Subnet_behind_clients' not found
use use App\Subnet_behind_clients(namespace of model) after namespace in controller
you forgot to add namespance of model in controller
try this
controller
use App\Subnet_behind_clients
public function show(Request $request)
{
$datas = Subnet_behind_clients::all();
return view('view2',compact('datas'));
}
view
#foreach($datas as $data)
<tr>
<td>{{ ++$i }}</td>
<td>{{ $data->ip_address }}</td>
<td>{{ $data->netmask }}</td>
</tr>
#endforeach

Resources