plbr plbr - 2 months ago 21
Ajax Question

Shopify / Cart.js / Update assigned and calculated variables?

Trying to calculate some values dynamically, but got stuck. Would love to calculate tax amounts and display them. Before cart.js we assigned temporary variables which worked perfectly well.

Needless to say those need to be updated now as well.

<div class="grid__item">
{% assign var_net = cart.total_price | divided_by:1.19 %}
{% assign var_tax = cart.total_price | minus: var_net %}
<p>
{{ cart.total_price | money_without_currency }} EUR<br/>
—<br/>
{{ var_net | money_without_currency }} EUR<br/>
{{ var_tax | money_without_currency }} EUR<br/>
—<br/>
{{ cart.total_price | money_without_currency }} EUR
</p>
</div>


This draws the price:

<span rv-html="cart.total_price"></span>


But how can we make the above calculation?

Answer

First off, you're going to want to make sure you're using the version of Cart.js that bundles Rivets.js (it comes as rivets-cartjs.min.js in Cart.js package).

You're then able to use a number of filters in your theme templates in a very similar way to Liquid - for example:

<div class="grid__item" data-cart-view>
  <p>
    <span rv-text="cart.total_price | money_without_currency">
      {{ cart.total_price | money_without_currency }}
    </span> EUR
  </p>
</div>

This will both render the total price on initial page load with Liquid, and keep the text of the <span> dynamically updated. Note the addition of the data-cart-view attribute, which tells Cart.js to dynamically update the contents of this element as the cart changes.

Implementing your var_net and var_tax dynamically will be a little more tricky. Cart.js does ship with math filters, but only plus and minus and they assume you're working only with integers (I just opened a ticket to fix that in the next release).

Fortunately, we can define our own formatters for Cart.js really simply! Try adding some code like this, after loading rivets-cart.min.js but before calling CartJS.init():

<script>
  rivets.formatters.var_net = function(price) {
    return price / 1.19;
  }
  rivets.formatters.var_tax = function(price) {
    return price - rivets.formatters.var_net(price);
  }
</script>

After doing that, you should be able to achieve both an accurate initial render in your Liquid code and keep things updated dynamically with a template like this:

<div class="grid__item" data-cart-view>
  {% assign var_net = cart.total_price | divided_by:1.19 %}   
  {% assign var_tax = cart.total_price | minus: var_net %}   
  <p>
    <span rv-text="cart.total_price | money_without_currency">
      {{ cart.total_price | money_without_currency }}
    </span> EUR<br/>
    —<br/>
    <span rv-text="cart.total_price | var_net | money_without_currency">
      {{ var_net | money_without_currency }}
    </span> EUR<br/>
    <span rv-text="cart.total_price | var_tax | money_without_currency">
      {{ var_tax | money_without_currency }}
    </span> EUR<br/>
    —<br/>
    <span rv-text="cart.total_price | money_without_currency">
      {{ cart.total_price | money_without_currency }}
    </span> EUR<br/>
  </p>
</div>