Total Cart Weight in Cart does not auto update when item quantities are changed.

Solved
Highlighted
Tourist
4 0 1

Hi, I'm using the Narrative theme and added the following code to my cart-template.liquid file:

Total Weight: {{ cart.total_weight | weight_with_unit }}

It shows up nicely. But when I try changing the item quantities in the cart, the total weight does not update accordingly. Only when I refresh the page, then I see the new weight. How do I make the weight auto update please?

Thanks.

0 Likes
Highlighted
Shopify Partner
601 71 98

@DeborahLi ,

You need to update using Ajax, changes will be required to make in theme.js. 

- Was my reply helpful? Click Like to let me know!
- Was your question answered? Click Accept as Solution

Skype : lokendra.panwar1

To hire: email us at shopify@propero.in
0 Likes
Highlighted
Excursionist
10 4 4

Hi, maybe you can do it this way:

 

On cart.template, add this above the ".cart-subtotal" div:

<div class="cart-total-weight">
  <span class="cart-weight__title h4">Total weight</span>
  <span class="cart-subtotal__price " data-cart-weight>{{ cart.total_weight | weight_with_unit }}</span>
</div>

 I have reused the ".cart-subtotal__price" because it's styling, you cant create a new class if you want.

 

Then make this changes on theme.js:

1. Append "cartWeight: '[data-cart-weight]'" to selectors$8, so you have:

var selectors$8 = {
  ajaxCart: '.cart-drawer',
  itemList: '[data-cart-item-list]',
  item: '[data-cart-item]',
  itemId: '[data-cart-item-id]',
  itemHref: '[data-cart-item-href]',
  itemImage: '[data-cart-item-image]',
  itemBackgroundImage: '[data-cart-item-background-image]',
  itemTitle: '[data-cart-item-title]',
  itemVariantTitle: '[data-cart-item-variant-title]',
  itemPropertyList: '[data-cart-item-property-list]',
  itemProperty: '[data-cart-item-property]',
  itemDiscountList: '[data-cart-item-discount-list]',
  itemDiscount: '[data-cart-item-discount]',
  itemDiscountTitle: '[data-cart-item-discount-title]',
  itemDiscountAmount: '[data-cart-item-discount-amount]',
  itemLabelQuantity: '[data-cart-item-label-quantity]',
  itemInputQuantity: '[data-cart-item-input-quantity]',
  itemDelete: '[data-cart-item-delete]',
  itemPriceContainer: '[data-cart-item-price-container]',
  itemLinePriceContainer: '[data-cart-item-line-price-container]',
  itemMessage: '[data-item-message]',
  cartDiscountContainer: '[data-cart-discount-container]',
  cartDiscount: '[data-cart-discount]',
  cartDiscountTitle: '[data-cart-discount-title]',
  cartDiscountAmount: '[data-cart-discount-amount]',
  cartNoteContainer: '[data-cart-note-container]',
  cartNoteInput: '[data-cart-note]',
  cartMessage: '[data-cart-message]',
  cartSubtotal: '[data-cart-subtotal]',
  cartSubmit: '[data-cart-submit]',
  cartWeight: '[data-cart-weight]'
};

 

And then add this snippet of code inside "_createCart", just before "return $container":

var weightUnit = $(selectors$8.cartWeight, $container).text().split(" ")[1];
$(selectors$8.cartWeight, $container).html(
    parseFloat(state.total_weight / 1000).toFixed(1) + " " + weightUnit
);

 

Should work this way. Remember that theme.js is unminified, so to see this changes you must change theme.liquid and reference "theme.js" instead of "theme.min.js". You also should minify theme.js before going live.

0 Likes
Highlighted
Tourist
4 0 1

@EnriqueMelero, I followed your instructions and changed the code according. But it didn't work.

Am not sure what you mean by your last paragraph "Remember that theme.js is unminified, so to see this changes you must change theme.liquid and reference "theme.js" instead of "theme.min.js". You also should minify theme.js before going live."

Do you mean change the file name? won't it affect the other files?

Sorry if I'm being a noob. Appreciate your patience and help. Thanks.

0 Likes
Highlighted
Tourist
4 0 1

@Propero, how I do that please? thanks tons.

1 Like
Highlighted
Excursionist
10 4 4

@DeborahLi You need to change this on theme.liquid

<script src="{{ 'theme.min.js' | asset_url }}" defer="defer"></script>

For this:

<script src="{{ 'theme.js' | asset_url }}" defer="defer"></script>

theme.js (where you made the changes) is the "readable" version of theme.min.js, but keeping unminified code on live websites it's not the best practice. It should work anyway.

I will try to put a theme-agnostic solution that doesn't modify existent js here on my next break

0 Likes
Highlighted
Excursionist
10 4 4

This is an accepted solution.

Hi again. This is a more universal approach, so it should work on almost any theme (put it on custom.js or equivalent):

 

var s_ajaxListener = new Object();
s_ajaxListener.tempOpen = XMLHttpRequest.prototype.open;
s_ajaxListener.tempSend = XMLHttpRequest.prototype.send;

XMLHttpRequest.prototype.open = function(a,b) {
  if (!a) var a='';

  if (!b) var b='';
  s_ajaxListener.tempOpen.apply(this, arguments);
  s_ajaxListener.method = a;  
  s_ajaxListener.url = b;
  if (a.toLowerCase() == 'get') {
    s_ajaxListener.data = b.split('?');
    s_ajaxListener.data = s_ajaxListener.data[1];
  }
}

XMLHttpRequest.prototype.send = function(a,b) {
  if (!a) var a='';
  if (!b) var b='';
  s_ajaxListener.tempSend.apply(this, arguments);
  if(s_ajaxListener.method.toLowerCase() == 'post')s_ajaxListener.data = a;
  s_ajaxListener.callback();
}

s_ajaxListener.callback = function () {     
  if (this.url.indexOf('/cart/change.js') != -1){         
    setTimeout(function(){ 
      var xhttp = new XMLHttpRequest();
      var elem = document.querySelector('[data-cart-weight]');
      var unit = elem.innerText.split(" ")[1]
      xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
          elem.textContent = parseFloat(JSON.parse(this.response).total_weight / 1000).toFixed(1) + " " + unit
        }
      };
      xhttp.open("GET", "/cart.js", true);
      xhttp.send();
    }, 500);
  }
}

 

This also needs this code below on cart-template:

 

<div class="cart-total-weight">
  <span class="cart-weight__title h4">Total weight</span>
  <span class="cart-subtotal__price " data-cart-weight>{{ cart.total_weight | weight_with_unit }}</span>
</div>

 

It has a 500 ms delay, because im not using callbacks included in theme.js so it can work anywhere.

1 Like
Highlighted
Tourist
4 0 1

@EnriqueMelero, it worked! thanks so much!!!

0 Likes