mnm.mtl
mnm.mtl

Reputation: 51

Livewire render function doesn't automatically update on browserEvent

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">&times;</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

Answers (1)

Prospero
Prospero

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

Related Questions