skip to Main Content

I’m doing system to buy promotion for ads, so each ad can have Stars and Days. I need to count sum of points for each Ad, then summ all points needed for all ads. Problem is that Total is always zero and I get no error. Why?

<div x-data="{ total: 0 }">
  <div class="flex" x-data="{ days: 1, stars: 1 }">
    <select x-model="days" @change="updateTotal()">
      <option value="1">1 day</option>
      <option value="2">2 days</option>
      <option value="3">3 days</option>
    </select>

    <select x-model="stars" @change="updateTotal()">
      <option value="1">1 star</option>
      <option value="2">2 stars</option>
      <option value="3">3 stars</option>
    </select>

    <div x-text="days * stars" id="sum"></div>
  </div>

  <div class="flex" x-data="{ days: 1, stars: 1 }">
    <select x-model="days" @change="updateTotal()">
      <option value="1">1 day</option>
      <option value="2">2 days</option>
      <option value="3">3 days</option>
    </select>

    <select x-model="stars" @change="updateTotal()">
      <option value="1">1 star</option>
      <option value="2">2 stars</option>
      <option value="3">3 stars</option>
    </select>

    <div x-text="days * stars" id="sum"></div>
  </div>

  <div class="flex" x-data="{ days: 1, stars: 1 }">
    <select x-model="days" @change="updateTotal()">
      <option value="1">1 day</option>
      <option value="2">2 days</option>
      <option value="3">3 days</option>
    </select>

    <select x-model="stars" @change="updateTotal()">
      <option value="1">1 star</option>
      <option value="2">2 stars</option>
      <option value="3">3 stars</option>
    </select>

    <div x-text="days * stars" id="sum"></div>
  </div>

  <div x-text="'Total: ' + total"></div>

  <script src="https://cdn.jsdelivr.net/npm/alpinejs@3"></script>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <script>
    $(document).ready(function() {
      updateTotal();
    });

    function updateTotal() {
      var total = 0;
      $('#sum').each(function() {
        var value = parseInt($(this).text());
        if (!isNaN(value)) {
          total += value;
        }
      });
      Alpine.store('total', total);
    }

    Alpine.data('example', () => ({
      total: Alpine.store('total'),

      mounted() {
        this.$watch('$refs.sum', () => {
          updateTotal();
          this.total = Alpine.store('total');
        });
      },
    }));
  </script>
</div>

2

Answers


  1. I’m not 100% confident but, first, you have multiple id="sum" where it should be unique. It only gets the first element. Instead, you can use a class.

    <div x-text="days * stars" class="sum"></div>
    

    So it would give

    $('.sum').each(function() {
        var value = parseInt($(this).text());
        if (!isNaN(value)) {
          total += value;
        }
    });
    Alpine.store('total', total);
    

    Everything together:

    <div x-data="{ total: 0 }">
      <div class="flex" x-data="{ days: 1, stars: 1 }">
        <select x-model="days" @change="updateTotal()">
          <option value="1">1 day</option>
          <option value="2">2 days</option>
          <option value="3">3 days</option>
        </select>
    
        <select x-model="stars" @change="updateTotal()">
          <option value="1">1 star</option>
          <option value="2">2 stars</option>
          <option value="3">3 stars</option>
        </select>
    
        <div class="sum" x-text="days * stars"></div>
      </div>
    
      <div class="flex" x-data="{ days: 1, stars: 1 }">
        <select x-model="days" @change="updateTotal()">
          <option value="1">1 day</option>
          <option value="2">2 days</option>
          <option value="3">3 days</option>
        </select>
    
        <select x-model="stars" @change="updateTotal()">
          <option value="1">1 star</option>
          <option value="2">2 stars</option>
          <option value="3">3 stars</option>
        </select>
    
        <div class="sum" x-text="days * stars"></div>
      </div>
    
      <div class="flex" x-data="{ days: 1, stars: 1 }">
        <select x-model="days" @change="updateTotal()">
          <option value="1">1 day</option>
          <option value="2">2 days</option>
          <option value="3">3 days</option>
        </select>
    
        <select x-model="stars" @change="updateTotal()">
          <option value="1">1 star</option>
          <option value="2">2 stars</option>
          <option value="3">3 stars</option>
        </select>
    
        <div class="sum" x-text="days * stars"></div>
      </div>
    
      <div x-text="'Total: ' + total"></div>
    
      <script src="https://cdn.jsdelivr.net/npm/alpinejs@3"></script>
      <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
      <script>
        function updateTotal() {
          var total = 0;
          $('.sum').each(function() {
            var value = parseInt($(this).text());
            if (!isNaN(value)) {
              total += value;
            }
          });
          Alpine.store('total', total);
        }
    
        $(document).ready(function() {
          updateTotal();
        });
    
        Alpine.data('example', () => ({
          total: Alpine.store('total'),
    
          mounted() {
            this.$watch('$refs.sum', () => {
              updateTotal();
              this.total = Alpine.store('total');
            });
          },
        }));
      </script>
    </div>
    
    
    Login or Signup to reply.
  2. jQuery is completely unnecessary here, you should use Alpine.js’ data model inside the component. A single reduction function call is enough to get the total points.

    <script defer src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>
    <div x-data="{ promos: {
                      promo1: {days: 1, stars: 1},
                      promo2: {days: 1, stars: 1},
                      promo3: {days: 1, stars: 1},
                  },
    
                  get total() {
                    return Object.values(this.promos).reduce((acc, cur) => acc + cur.days*cur.stars, 0)
                  }
      }">
      <div class="flex">
        <select x-model.number="promos.promo1.days">
          <option value="1">1 day</option>
          <option value="2">2 days</option>
          <option value="3">3 days</option>
        </select>
    
        <select x-model.number="promos.promo1.stars">
          <option value="1">1 star</option>
          <option value="2">2 stars</option>
          <option value="3">3 stars</option>
        </select>
    
        <div class="sum" x-text="promos.promo1.days * promos.promo1.stars"></div>
      </div>
    
      <div class="flex">
        <select x-model.number="promos.promo2.days">
          <option value="1">1 day</option>
          <option value="2">2 days</option>
          <option value="3">3 days</option>
        </select>
    
        <select x-model.number="promos.promo2.stars">
          <option value="1">1 star</option>
          <option value="2">2 stars</option>
          <option value="3">3 stars</option>
        </select>
    
        <div class="sum" x-text="promos.promo2.days * promos.promo2.stars"></div>
      </div>
    
      <div class="flex">
        <select x-model.number="promos.promo3.days">
          <option value="1">1 day</option>
          <option value="2">2 days</option>
          <option value="3">3 days</option>
        </select>
    
        <select x-model.number="promos.promo3.stars">
          <option value="1">1 star</option>
          <option value="2">2 stars</option>
          <option value="3">3 stars</option>
        </select>
    
        <div class="sum" x-text="promos.promo3.days * promos.promo3.stars"></div>
      </div>
    
      <div x-text="`Total: ${total}`"></div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search