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');
}
}