skip to Main Content

I would like to call a function called "syncBudget"

<div wire:key="extendForm" class="card p-3 border-0 shadow-sm space-y-3" x-data="() => {
    return {
        length: @entangle('length'),
        lengthType: @entangle('lengthType'),
        coupon: @entangle('coupon'),
        partnerPackage: {{ $partnerPackage }},
        total: @entangle('total'),
        couponDiscount: @entangle('couponDiscount'),
        lengthDiscount: @entangle('lengthDiscount'),
        amountToPay: @entangle('amountToPay'),
        syncBudget: function() {
            const coupon = this.coupon;
            const data = this.partnerPackage;
            let price = data['price']
            // Applying length discount
            if (this.lengthType == 'monthly') {
                this.total = price * this.length;
            } else if (this.lengthType == 'yearly') {
                this.total = (price * 12) * this.length;
                this.lengthDiscount = (this.total / 100) * 10;
            }
            this.amountToPay = this.total - this.lengthDiscount;
            // Applying coupon discount
            this.couponDiscount = (this.amountToPay / 100 * coupon['discount']);
            this.amountToPay -= this.couponDiscount;
        }
    }
}">

Need to call it from a livewire function

#[On('apply-coupon')]
public function applyCoupon(Coupon $coupon){
    $this->coupon = $coupon->toArray();
    $this->dispatch('syncBudget');
}

The flow is, when user apply a coupon. It should dispatch "syncBudget" function. I cant find it in both livewire and alpinejs documentation. Can anyone help me to achieve this one? Thank you

2

Answers


  1. You could do this way inside your apline js component:

    <div wire:key="extendForm" class="card p-3 border-0 shadow-sm space-y-3" x-data="blahhhh,
    listenForLivewireUpdates() {
            Livewire.on('syncBudget') => {
                this.syncBudget();
            });
        },
    "
    x-init="listenForLivewireUpdates();"
    >
    
    Login or Signup to reply.
  2. I see some things that can be improved here

    • you don’t need to assign a function to x-data object when defined as HTML attribute, it can be a simple JSON object: x-data="{ propertyA: null, functionB: function {return null;} }"

    • your x-data object is quite large so it would be better to define it as external Javascript code (yes, in this case you need to define a function that returns an object)

    • the AlpineJS code accesses many Livewire properties using @entangle. @entangle is present in Livewire 3 mainly for backwards compatibility since component properties can now be accessed via the $wire object

    • it seems like you are applying a business-logic in the frontend side: this is not a good practice since anyone can tamper with the code. The business logic should stay in the backend

    Note that it is not clear where the $partnerPackage comes from, if it is data passed to the view it should be accessed as {{ Js::from($partnerPackage) }} or @json($partnerPackage)
    Also it’s not clear why you are assigning a wire:key to your <div>

    So, this is your revised code, with the required functionality added:

    <div wire:key="extendForm"
         class="card p-3 border-0 shadow-sm space-y-3"
         x-data="syncBudgetObject"
    >
        <!-- -->
    </div>
    
    @script
    <script>
    
        Alpine.data("syncBudgetObject", () => ({
    
            partnerPackage: {{ Js::from($partnerPackage) }}, // adapt this if needed
    
            init: function(){
    
                $wire.on('syncBudget', () => {
                    this.syncBudget();
                });
            },
    
            syncBudget: function() {
    
                const price = this.partnerPackage.data['price'];
    
                // Applying length discount
                if ($wire.lengthType == 'monthly') {
    
                    $wire.total = price * $wire.length;
    
                } else if ($wire.lengthType == 'yearly') {
    
                    $wire.total = (price * 12) * $wire.length;
                    $wire.lengthDiscount = ($wire.total / 100) * 10;
                }
    
                $wire.amountToPay = $wire.total - $wire.lengthDiscount;
    
                // Applying coupon discount
                $wire.couponDiscount = ($wire.amountToPay / 100 * $wire.coupon['discount']);
                $wire.amountToPay -= $wire.couponDiscount;
            }
    
        }));
    
    </script>
    @endscript
    

    But I strongly suggest you move the logic to the backend side

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search