skip to Main Content

Using AlpineJS I have the following:

<div x-data="pricing()" x-init="data = { plan: 'a' }">

  <p><span x-text="calculate() + '€'"></span>per session</p>

  <select x-model="data.plan">
    <option value="a">A</option>
    <option value="b">B</option>
  </select>

</div>

export default function pricing() {

  return {

    data: {
      plan: "",
    },  

    calculate() {
      if (this.data.plan == "a")
        return 20;

      return 30;
    }
  }
}

How to hide the span if calculate() returns null?

2

Answers


  1. Your x-model controlled element needs to be inside your x-data container:

    <div x-data="pricing()" x-init="data = { plan: 'a' }">
      <p><span x-show="calculate()" x-text="calculate() + '€'"></span>per session</p>
      <select x-model="data.plan">
        <option value="a">A</option>
        <option value="b">B</option>
      </select>
    </div>
    

    EDIT: to avoid calling calculate() twice each time, you can store the result inside the data object and recalculate it each time the model changes with the x-on:change attribute:

    <div x-data="pricing()" x-init="data = {plan: 'a', priceVal: 20}">
      <p>
        <span x-text="data.priceVal + '€'" x-show="data.priceVal"></span>per
        session
      </p>
      <select x-model="data.plan" x-on:change="calculate()">
        <option value="a">A</option>
        <option value="b">B</option>
      </select>
    </div>
    
    export default function pricing() {
      return {
        data: {
          plan: "",
          priceVal: 20,
        },
    
        calculate() {
          if (this.data.plan == "a") {
            this.data.priceVal = 20;
          } else {
            this.data.priceVal = 30;
          }
        },
      };
    }
    

    This might be more efficient, but the ‘Alpine way’ would probably just be to call the function twice.

    Login or Signup to reply.
  2. An option can be adding a "watch" on the value:

    <div x-data="pricing('a')">
    
        <p><span x-show="calculatedPrice" x-text="calculatedPrice + '€'"></span> per session</p>
    
        <select x-model="data.plan">
            <option value=""></option>
            <option value="a">A</option>
            <option value="b">B</option>
        </select>
    
    </div>
    
    function pricing(initialValue = null) {
    
        return {
    
            data: {
                plan: initialValue,
            },
    
            calculatedPrice: null,
    
            init() {
    
                this.$watch('data.plan', () => this.calculate());
                this.calculate();
            },
    
            calculate() {
    
                switch (this.data.plan)
                {
                    case "a":
                        this.calculatedPrice = 20;
                        break;
    
                    case "b":
                        this.calculatedPrice = 30;
                        break;
    
                    default:
                        this.calculatedPrice = null;
                        break;
                }
            }
        }
    }
    

    In this example I’ve moved the init() function in the data object, passing the initial parameter

    If you want to completely hide the price row, you must move x-show in the <p> tag:

    <p x-show="calculatedPrice">
       <span x-text="calculatedPrice + '€'"></span> per session
    </p>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search