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 AppHttpLivewire;
    
    use LivewireComponent;
    use AppModelsBooks;
    
    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>

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x