Laravel Livewire component not re-rendering - laravel

I have a notifications component that I'm trying to emit an event to and get it to refresh and show new notifications to the user. I've verified that I'm receiving the event, and the refreshNotifications method is being called, but no matter what I try I can't seem to get the actual component to update. It's getting super frustrating at this point.
Here's my component:
namespace App\Http\Livewire\Components;
use Livewire\Component;
use Illuminate\Support\Facades\Auth;
class Notifications extends Component
{
public $notifications;
public $notificationCount = 0;
protected $listeners = ['refreshNotifications'];
public function mount()
{
$this->user = Auth::user();
}
public function render()
{
$this->notifications = $this->user->fresh()->unreadNotifications;
$this->notificationCount = $this->user->fresh()->unreadNotifications->count();
return view('livewire.components.notifications');
}
public function clearNotifications()
{
$this->user->unreadNotifications()->update(['read_at' => now()]);
}
public function refreshNotifications()
{
//can verify here that the event successfully emitted to this component. No refresh happens though.
$this->render();
}
}
And here's my blade view:
<li class="nav-item dropdown" x-data="{ open: false }">
<a #click="open = !open" #click.outside="open = false" class="nav-link dropdown-toggle show" id="notificationDropdown" role="button">
<i class="mdi mdi-bell-outline h3"></i>
#if ($notificationCount)
<div class="indicator">
<div class="circle"></div>
</div>
#endif
</a>
<div x-show="open" class="dropdown-menu p-0 show" data-bs-popper="none">
<div class="px-3 py-2 d-flex align-items-center justify-content-between border-bottom">
<p>{{ $notificationCount }} New Notifications</p>
#if ($notificationCount)
<a role="button" wire:click="clearNotifications" class="text-muted"><i class="mdi mdi-notification-clear-all"></i>Clear all</a>
#endif
</div>
#foreach ($notifications as $notification)
<div class="px-3 py-2" wire:key="notification-{{ $notification->id }}">
<a role="button" class="d-flex align-items-center py-2">
<div class="flex-grow-1 me-2">
<h5>{{ $notification->data['title'] ?? 'Test Title' }}</h5>
<p class="tx-14 text-muted"><em>{{ $notification->data['body'] ?? 'Test body' }}</em></p>
<p class="tx-12 text-muted">{{ Helper::timeElapsedForHumans($notification->created_at) }}</p>
</div>
</a>
</div>
#endforeach
</div>
</li>
Not sure if it's helpful, but the xhr response is this: {"effects":{"html":null,"dirty":[]},"serverMemo":{"checksum":"c980388fe95899e9055bfc363bd57c5d80916fe581b5b7983109cdba20db2f33"}}
Other questions on SO are related to not being in a single root element. That's not my issue. I have no idea why this isn't working. I feel like I've tried everything.

You need to define what event is called in the listener, for example:
protected $listeners = ['refreshNotifications' => '$refresh'];
See here:
https://laravel-livewire.com/docs/2.x/actions#magic-actions

Related

How do I do pagination on my code in Laravel?

So my front-end Lists of Businesses are not in paginated style. But I do not know how to do it. Can anyone please help? The code I posted is in my BusinessListController.php
BusinessListController.php
`<?php
namespace App\Http\Controllers;
use App\Models\Business;
use App\Models\Category;
use App\Models\Location;
use Illuminate\Http\Request;
class BusinessListController extends Controller
{
public function index(Request $request)
{
$businesses = Business::query()
->with('location')
->whereFilters($request->only(
['search', 'category', 'location']
))
->get();d
return view('pages.business-list', [
'businesses' => $businesses,
'locations' => Location::all(),
'categories' => Category::all()
]);
}
}`
And then here is the code for my view blade front-end
Business-List.blade.php
<div class="row business-list-row mx-auto">
#foreach ($businesses as $business)
<div class="col-md-4">
<div class="card shadow border-light mb-3">
<img
src="https://cdn1.clickthecity.com/images/articles/content/5d6eba1f4795e0.58378778.jpg"
class="card-img-top" alt="...">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h4 class="card-title h6" style="font-weight: bold;">
{{Str::limit($business->name, 20, $end='...')}}
</h4>
<div class="">
<p class="card-text">
{{ $business->location?->name }}
</p>
<p class="card-text" style="color: #32a852;">
{{ $business->category?->name}}
</p>
</div>
</div>
<div class="align-self-center">
<a href="{{ route('store', $business->id) }}" class="btn btn-info stretched-link">
Visit
</a>
</div>
</div>
</div>
</div>
</div>
#endforeach
</div>
So you need to do three things.
In Controller:
$businesses = Business::query()
->with('location')
->whereFilters($request->only(
['search', 'category', 'location']
))
->paginate(15);
put the number of items you need on a single page. here I put 15.
Put this under the </div> of your list.
{{ $business->links() }}
Put this inside the App\Providers\AppServiceProvider boot method.
use Illuminate\Pagination\Paginator;
public function boot()
{
Paginator::useBootstrapFive(); // or
Paginator::useBootstrapFour();
}
This depends upon which version of Bootstrap you are using.
Still confused? Checkout Laravel Pagination Documentation
Just remove ->get();d and add paginate
example
ModelName()->paginate();

limit () and take () not working properly

im trying to take 3 most viewed post but its just getting only two I don't know why I have tried limit () method it's not showing anything what am I doing wrong here ,
<?php
namespace App\Http\Livewire;
use App\Models\Movie;
use Livewire\Component;
class MovieBox extends Component
{
public function render()
{
return view('livewire.movie-box',[
'movies' => Movie::withCount('read_count')->orderBy('reads', 'desc')->take(3)->get(),
]);
}
}
movie box
<div>
<div class="relative grid grid-cols-3 gap-2 mt-3 user_story md:grid-cols-5">
#foreach ( $movies as $movie )
<a href="#create-post" uk-toggle="target: body ; cls: story-">
<div class="single_story">
<img src="assets/images/avatars/avatar-lg-1.jpg" alt="">
<div class="story-avatar"> <img src="assets/images/avatars/avatar-1.jpg" alt=""></div>
<div class="story-content">
<h4> {{ $movie->title }}</h4>
</div>
</div>
</a>
#endforeach
<span
class="absolute z-10 items-center justify-center hidden p-2 -mr-4 text-xl bg-white rounded-full shadow-md lg:flex w-9 uk-position-center-right"
uk-toggle="target: body ; cls: story-">
<i class="icon-feather-chevron-right"></i></span>
</div>
Change your render method like this.
public function render()
{
return view('livewire.movie-box',[
'movies' => Movie::withCount('read_count')->orderBy('reads', 'desc')->limit(3)->get(),
]);
}

LaravelShoppingcart package, rowId property not working

Hi I'm using the LaravelShoppingcart package(https://github.com/bumbummen99/LaravelShoppingcart) and When I output {{ $item->rowId }} on the blade template I get the rowId on the browser when the blade is rendered but when I pass it in the qtyIncreased({{ $item->rowId}}) method and try to dump and die it in the livewire component it doesn't work. Mark you when I pass the $item->id and dump and die it, it works. The only error I'm getting is on the console and is:
Error handling response: TypeError: Cannot destructure property 'yt' of 'undefined' as it is undefined.
at chrome-extension://cmedhionkhpnakcndndgjdbohmhepckk/scripts/contentscript.js:535:6
Any assistance is highly appreciated.
Live wire blade component
<div class="cart-overlay {{ $active ? 'transparent' : '' }}">
<div class="cart {{ $active ? 'showCart' : '' }}">
<span class="close-cart" wire:click="$emit('closeCart')">
<i class="fas fa-window-close"></i>
</span>
<h2>Cart</h2>
<div class="cart-content">
#foreach ($cartContent as $item)
<div class="cart-item">
<img src="{{ $item->options->image }}" alt="product" />
<div>
<h4>{{ $item->name }}</h4>
<h5>${{ $item->price }}.99</h5>
<span class="remove-item">remove</span>
</div>
<div>
<i class="fas fa-chevron-up" wire:click="qtyIncreased({{ $item-
>rowId }})"></i>
<p class="item-amount">{{ $item->qty }}</p>
<i class="fas fa-chevron-down"></i>
</div>
</div>
#endforeach
</div>
<div class="cart-footer">
<h3>your total : $ <span class="cart-total">{{ $cartTotal }}</span></h3>
<button class="clear-cart banner-btn">clear cart</button>
</div>
</div>
</div>
Livewire Class component
<?php
namespace App\Http\Livewire;
use Gloudemans\Shoppingcart\Facades\Cart;
use Livewire\Component;
class CartOverlay extends Component
{
public $active = false;
public function render()
{
$cartContent = Cart::content();
$cartTotal = Cart::total();
return view('livewire.cart-overlay', compact(['cartContent', 'cartTotal']));
}
public $listeners = [
'showCart',
'closeCart'
];
public function qtyIncreased($rowId)
{
dd($rowId);
}
public function showCart()
{
$this->active = true;
}
public function closeCart()
{
$this->active = false;
}
}
I managed to fixed it, the parameter in the function should be passed in as a string. So, I added quotes around the parameter. Changed it from <i class="fas fa-chevron-up" wire:click="qtyIncreased({{ $item->rowId }})"></i>
TO
<i class="fas fa-chevron-up" wire:click="qtyIncreased('{{ $item->rowId }}')"></i>

How to fetch user's profile info related to user using laravel?

I want to fetch user's profile info related to user and i have already made relationship b/w user and profile one to one relation but I don't know how to fetch this?
Does anybody have an idea please help me thanks
Database table
Profile table has User_name,phone_number,Job ,user_id
controller
public function viewprofile()
{
return view('viewprofile');
}
profile model
class Profile extends Model
{
protected $table = 'Profiles';
protected $fillable = ['User_name', 'phone_number', 'Job'];
public function user()
{
return $this->belongsTo(User::class);
}
}
User model
class User extends Authenticatable
{
public function profile()
{
return $this->hasOne(Profile::class);
}
}
profile view
<div class="col-12 col-sm-6 col-md-4 d-flex align-items-stretch">
<div class="card bg-light">
<div class="card-header text-muted border-bottom-0">
Digital Strategist
</div>
<div class="card-body pt-0">
<div class="row">
<div class="col-7">
<h2 class="lead"><b>Name: Your Name</b></h2>
<p class="text-muted text-sm"><b>Job: </b> Web Designer / UX / Graphic Artist /
Coffee Lover </p>
<ul class="ml-4 mb-0 fa-ul text-muted">
<li class="small"><span class="fa-li"><i class="fas fa-lg fa-phone"></i></span>
Phone
#: + 800 - 12 12 23 52
</li>
</ul>
</div>
<div class="col-5 text-center">
<img src="../../dist/img/user1-128x128.jpg" alt="" class="img-circle img-fluid">
</div>
</div>
</div>
<div class="card-footer">
<div class="text-right">
<a href="#" class="btn btn-sm bg-teal">
<i class="fas fa-comments"></i>
</a>
<a href="#" class="btn btn-sm btn-primary">
<i class="fas fa-user"></i> View Profile
</a>
</div>
</div>
</div>
</div>
The users profile will be accessible through the relationship and you can get access to it by calling the relationship as a property:
$profile = auth()->user()->profile;
If you need to be able to display it in your view, then just pass it through:
public function viewprofile()
{
return view('viewprofile', ['profile' => auth()->user()->profile]);
}

I want to get a pop-up notification when new value in inserted in my mysql database table using Laravel

I want to show a successful message as notification in my home page when a new value is inserted into my database.
Controller
function insert(Request $request)
{
$teacher = new teacher;
$teacher->Teacher_name = $request->Teacher_name;
$teacher->School_name = $request->School_name;
$teacher->Date_of_Birth = $request->Date_of_Birth;
$teacher->save();
$teacher = teacher::find($request->id);
return back()->with('success', 'Data inserted Successfully');
}
View
<ul class="nav navbar-nav navbar-left">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><span
class="label label-pill label-danger count" style="border-
radius:10px;"></span> <span class="glyphicon glyphicon-bell"
style="font-size:18px;"></span></a>
<ul class="dropdown-menu">
</ul>
</li>
</ul>
In Laravel, you can show success or failure alerts using Flash as below,
Controller:
\Session::flash('success', 'Data inserted Successfully.');
Blade file:
#if ($message = \Session::get('success'))
<div class="alert success-msg">
{{ $message }}
</div>
#endif
UPDATE:
To keep message in blade until closed;
#if (session()->has('success'))
<div class="alert alert-dismissable alert-success">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<strong>
{!! session()->get('success') !!}
</strong>
</div>
#endif
UPDATE:2
To get real time notification, you can use Pusher and implementation guide for the same is: https://www.sitepoint.com/add-real-time-notifications-laravel-pusher/
Hope this helps.
Use Flash,
Controller:
\Session::flash('success', 'Data inserted Successfully.');
Blade file:
#if ($message = \Session::get('success'))
<div class="modal hide fade" id="myModal">
<div class="modal-header">
<a class="close" data-dismiss="modal">×</a>
<h3>Modal header</h3>
</div>
<div class="modal-body">
<p>{{$message}}</p>
</div>
<div class="modal-footer">
Close
</div>
</div>
<script> $('#myModal').modal('show');</script>
#endif
Post this after you Load jquery and bootstrap.

Resources