Search code examples
laravellaravel-livewirelivewireslivewire-3

Laravel Livewire not forgetting an array item values calculation when the function updates


i have loop of check box items

    @foreach ($product->productOptions as $productOption)
  <input class="form-check-input" wire:model.live="productOptionPriceId" type="checkbox"  value="{{ $productOption->id }}">   @endforeach                                            

and my livewire component function

    public function updated()
{
   
    $basePrice = (float)$this->basePrice;
    $selectedSizePrice = (float)$this->selectedSizePrice;
    if ($this->productSizeId > 0) {
        $model = ProductSize::select('price')->findOrFail($this->productSizeId);
        $this->selectedSizePrice = number_format($model->price, 2);
    }
    if (count($this->productOptionPriceId) > 0) {
        $option = ProductOption::select('price')->where('id', $this->productOptionPriceId)->get();
        foreach ($option as $item) {
            $this->selectedOptionPrice[] = number_format($item->price, 2);
        }
        $selectedOptionPrice = array_sum($this->selectedOptionPrice);
    } else {
        $selectedOptionPrice = 0;
    }
    $this->totalPrice = $basePrice + $selectedSizePrice + $selectedOptionPrice;

}

the broblem is when i checked input the value calculate and when uncheck and recheck add item an continue calculate not removing the unchecked value item this is the problem it not remove item from array and recalculate please help


Solution

  • The context is not entirely clear, since we can't see the relevant parts of the class and the view, so I will try to deduce some elements.

    productOptionPriceId must be an array which contains all the ids of the selected checkboxes and it is initialized to empty: public array $productOptionPriceId = [];

    With this in mind, we can change the code like this:

    public function updated()
    {
        $basePrice = (float)$this->basePrice;
        $selectedSizePrice = (float)$this->selectedSizePrice;
    
        if ($this->productSizeId > 0) {
            $model = ProductSize::select('price')->findOrFail($this->productSizeId);
            $this->selectedSizePrice = number_format($model->price, 2);
        }
    
        $selectedOptionPrice = ProductOption::whereIn('id', $this->productOptionPriceId)
                                            ->selectRaw('sum(case when `price` - truncate(`price`, 2) > 0.004 then round(`price`, 2) else truncate(`price`, 2) end) as total')
                                            ->first()['total'] ?? 0;
    
        // or, if rounding is not needed:
        // $selectedOptionPrice = ProductOption::whereIn('id', $this->productOptionPriceId)->sum('price');
        
        $this->totalPrice = $basePrice + $selectedSizePrice + $selectedOptionPrice;
    }
    

    If you prefer to continue using the PHP number_format() function you can proceed as follows:

    $selectedOptionPrice = ProductOption::whereIn('id', $this->productOptionPriceId)
                                        ->get('price')
                                        ->reduce(fn ($carry, $row) => $carry + number_format($row->price, 2), 0);
    

    Another option can be to store the prices as values of the checkboxes instead of ids and then sum them.