Reputation: 51
I just started learning Livewire and I am making a page to purchase books and add them to cart.
I made two Livewire components, one for the books and one for the cart. When I click purchase book everything works perfect and it was automatically added to the cart, but the problem is the cart doesn't update automatically and I need to reload the page to see the added books.
The books component:
class Book extends Component
{
public $book,$price;
protected $listeners = ['purchase' => 'incrementPrice'];
public function render()
{
return view('livewire.book', [
'books'=> Books::orderBy('id','asc')->get(),
'purchases'=> Books::where('purchased',1)->paginate(20)
]);
}
public function purchase($id)
{
$book = Books::find($id);
$book->purchased = 1;
$book->save();
if($book->save())
{
$this->dispatchBrowserEvent('bookPurchased');
}
}
public function cancel($id)
{
$book = Books::find($id);
$book->purchased = 0;
$book->save();
}
public function OpenModal()
{
$this->emit('OpenModal');
}
public function incrementPrice()
{
$this->total = $price;
}
}
The book Livewire component:
<div>
<button wire:click="OpenModal()" type="button" class="btn btn-dark">
@if( $purchases->total() >= 1 )
CART <span class="badge badge-light">( {{ $purchases->total() }} )</span>
@else
CART
@endif
</button>
<div class="row">
@foreach( $books as $book )
<div class="col-3">
<div class="card" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title" wire:model="book">{{ $book->book }}</h5>
<p class="card-text" wire:model="price"> ${{ $book->price }} </p>
@if( $book->purchased == 0 )
<a wire:click="purchase({{ $book->id }})" class="btn btn-primary">Purchase</a>
@else
<a class="btn btn-primary disabled">Purchase</a>
<a wire:click="cancel({{ $book->id }})" class="btn btn-warning ">cancel</a>
@endif
</div>
</div>
</div>
@endforeach
</div>
@livewire('cart')
</div>
This is my View:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>books</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
@livewireStyles
</head>
<body>
<br><br>
<div class="conatiner m-5">
@livewire('book')
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
@livewireScripts
<script>
window.addEventListener('bookPurchased', function(){
alert('book was purchased !');
});
livewire.on('OpenModal' , ()=>{
$('.Cart').modal('show');
});
</script>
</body>
</html>
The cart component:
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Books;
class Cart extends Component
{
public function render()
{
return view('livewire.cart', [
'purchases'=> Books::where('purchased',1)->get()
]);
}
}
And this is the Cart Livewire component I am using as a modal:
<div>
<div class="modal fade Cart" wire:ignore.self id="exampleModalLong" tabindex="-1" role="dialog" aria-labelledby="exampleModalLongTitle" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">CART</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
@foreach( $purchases as $purchase )
<div class="card">
<div class="card-body">
<p>{{ $purchase->book }}</p>
<p wire:model="p_price">${{ $purchase->price }}</p>
</div>
<br>
</div>
@endforeach
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
Upvotes: 0
Views: 1575
Reputation: 2352
you can use events for achieve it. Once you save the book, emit an event to Cart component to refresh it.
//book component...
...
$book->save();
$this->emit('cartRefresh');
...
//cart component
protected $listeners = ['cartRefresh' => '$refresh']; //it's going to re-render the component
Upvotes: 1