Home > database >  Combining Multiple Laravel Livewire "updated" Lifecycle Hooks Into a Single Function
Combining Multiple Laravel Livewire "updated" Lifecycle Hooks Into a Single Function

Time:06-13

I need to update the price on the page when a user changes the value of either the width, height and/or length. The code below works, but it seems it could be cleaner instead of having three separate updated lifecycle hooks with duplicate code. When the view is mounted, I set the default values of width, height and length and calculate the price.

show.php

...
class Show extends Component
{
    public $product;
    public $sku;
    public $name;
    public $description;
    public $width;
    public $height;
    public $length;
    public $price;

    public function mount(Product $product){
        $this->product = $product;
        $this->sku = $product->sku;
        $this->name = $product->name;
        $this->description = $product->description;

        $this->width = 4;
        $this->height = 4;
        $this->length = 10;
        $this->price = (((($this->width   $this->height   $this->height)*12)/144)*25)*$this->length;
    }

    public function updatedWidth() {
        $width = $this->width;
        $height = $this->height;
        $length = $this->length;
        $this->price = (((($width   $height   $height)*12)/144)*25)*$length;
    }

    public function updatedHeight() {
        $width = $this->width;
        $height = $this->height;
        $length = $this->length;
        $this->price = (((($width   $height   $height)*12)/144)*25)*$length;
    }

    public function updatedLength() {
        $width = $this->width;
        $height = $this->height;
        $length = $this->length;
        $this->price = (((($width   $height   $height)*12)/144)*25)*$length;
    }

    public function render()
    {
        return view('livewire.shop.show')->layout('layouts.frontend');
    }
}

show.blade.php

   ...
    <div >
        <h1 >{{$product->name}}</h1>
    
        <div >
            <h2 >Product information</h2>
            <p wire:model="price" >${{number_format($price, 2, '.')}}</p>
        </div>
    
        <div >
            <h3 >Description</h3>
    
            <div >
                <p>
                    {{$product->description}}
                </p>
            </div>
        </div>
    
        <form wire:submit.prevent="createOrderItem" method="POST" >
            <div>
                <h3 >Size</h3>
    
                <div >
                    <div >
                        <label for="width" >Outer Width:</label>
                        <select wire:model="width" id="width" name="width" >
                            <option value="3">3"</option>
                            <option value="4">4"</option>
                            <option value="5">5"</option>
                        </select>
                    </div>
    
                    <div >
                        <label for="height" >Outer Height:</label>
                        <select wire:model="height" id="height" name="height" >
                            <option value="3">3"</option>
                            <option value="4">4"</option>
                            <option value="5">5"</option>
                        </select>
                    </div>
    
                    <div >
                        <label for="length" >Length:</label>
                        <select wire:model="length" id="length" name="length" >
                            <option value="10">10'</option>
                            <option value="11">11'</option>
                            <option value="12">12'</option>
                        </select>
                    </div>
                </div>
            </div>
    ...

CodePudding user response:

Since you are doing the same calculation multiple times, it would make sense to extract that into its own method. Then, you can use the "global" updated() lifecycle-hook and conditionally set the price based on which fields were updated.

class Show extends Component
{
    public $product;
    public $sku;
    public $name;
    public $description;
    public $width;
    public $height;
    public $length;
    public $price;

    public function mount(Product $product) 
    {
        $this->product = $product;
        $this->sku = $product->sku;
        $this->name = $product->name;
        $this->description = $product->description;

        $this->width = 4;
        $this->height = 4;
        $this->length = 10;
        $this->price = $this->calculatePrice();
    }

    /**
     * Calculates the price based on height, width and length 
     * @return int $calculatedPrice
     */
    private function calculatePrice() 
    {
        return (((($this->width   (2 * $this->height)) * 12) / 144) * 25) * $this->length;
    }

    /**
     * Life-cycle hook that will fire on each updated value from the view
     * @param string $field The fieldname that is updated
     */
    public function updated($field) 
    {
        if (in_array($field, ['width', 'height', 'length'])) {
            $this->price = $this->calculatePrice();
        }
    }

    public function render()
    {
        return view('livewire.shop.show')
                ->layout('layouts.frontend');
    }
}
  • Related