4

I've been trying all day long to include this liquid code inside javascript with no luck so far..

I'm simply trying to update a div with the cart data to show the image and name, this is what I've got.

$('.openCart').click(function(e)
{          
    $.ajax({
        type: 'POST',
        url: '/cart/add.js',
        data: data,
        dataType: 'json',
        success: function()
        {
          {% capture content %}{% include 'addItemToCartDetails' %}{% endcapture %}
          var content = {{ content | json }};
          $("._second").html(content);
        }
    });
 });

Overall the following code doesn't work(simply because of the for loop, and I have no clue how to get around this..): If I remove the for loop then the code retrieves the divs and everything, besides the item data since the loop isn't working.

This is the addItemToCartDetails.liquid,

{% for item in cart.items %}

    <div class="_second_1">
      <a href="{{ item.url | widivin: collections.all }}" class="cart-image">
        <img width="320" src="{{ item | img_url: '700x700' }}" alt="{{ item.title | escape }}">
      </a>
    </div>

    <div class="_second_2"><h3>Product Name</h3>{{ item.product.title }}</div>

    <div class="_second_3"><h3>Remove Product</h3><span class="clearCart">Remove</span></div>

    <div class="_second_4"><h3>Quantity</h3><input class="quantity" type="input" name="updates[]" id="updates_{{ item.id }}" value="{{ item.quantity }}" min="0" data-id="{{ item.id }}" title="If you'd like another subscription please checkout separately" alt="If you'd like another subscription please checkout separately" disabled></div>

    <div class="_second_5">
      <h3>Total Price</h3>

      <div class="totalDetails">Total: {{ item.line_price | plus: 0 | money }} / month</div>

    </div>

    <div class="_third">
      <input type="submit" name="checkout" value="PROCEED TO CHECKOUT">
    </div>

{% endfor %}
4
  • In the JavaScript code, remove the trailing } Commented Sep 18, 2016 at 23:11
  • @jrbedard sorry, I forgot to fix that, the live site is already fixed but that wasn't the problem though, issue still maintains. :/ Commented Sep 18, 2016 at 23:12
  • Did you try passing the variable {% include 'addItemToCartDetails', items: cart.items %} then the for loop in the other file {% for item in items %} Commented Sep 18, 2016 at 23:21
  • To answer the question you asked, is your openCart click function in a snippet or in an asset file? However, I have a feeling that what you're trying to do is the wrong approach - could you clarify exactly what you're trying to do? If you're trying to update the DOM after a product gets added to show the most recently added product, there are much better ways to approach the problem. Commented Sep 19, 2016 at 18:13

3 Answers 3

6

You are trying to use Liquid when you should be using Javascript

All of the Liquid processing happens on the backend to construct an HTML file that gets passed to the browser. Once the HTML page has been passed to the user's browser, Javascript can be used to manipulate the document and make this appear/disappear/change.

Practically, this means that your {% for item in cart.items %} in addItemToCartDetails.liquid will be rendered once, before page load, and never again afterwards. No matter how many items are added to the cart, the results of that snippet will only ever be current as of page load.

You should be using the Javascript variables instead

Shopify passes the line item object representing the most recently-added product to your success callback function. Your code should look something like this:

$('.openCart').click(function(e)
{          
    $.ajax({
        type: 'POST',
        url: '/cart/add.js',
        data: data,
        dataType: 'json',
        success: function(line_item)
        {
          var content = '<h3>You added a ' + line_item.title + '!</h3>' +
                        '<p> We appreciate that you want to give us ' + Shopify.formatMoney(line_item.line_price, {{ shop.money_format }}) + '!</p>' + 
                        '<p>That is very nice of you!  Cheers!</p>';
          // Note: Not every theme has a Shopify.formatMoney function.  If you are inside an asset file, you won't have access to {{ shop.money_format }} - you'll have to save that to a global javascript variable in your theme.liquid and then reference that javascript variable in its place instead.
          $("._second").html(content);
        }
    });
 });

If you're curious about what all you can access in the response object, add a console.log(line_item) to the beginning of your success function to print the object to your browser's console. (In most browsers you can right-click any element on the page and select 'Inspect Element' to bring up your developer tools. There should be a tab called 'Console' where the logs get printed to, and once your information is there you should be able to click on the object to expand its contents.)

Sign up to request clarification or add additional context in comments.

1 Comment

To be absolutely clear: You can use Liquid in JavaScript, but only if you understand what's happening. Liquid gets processed server-side to dynamically generate a text output which can be HTML or it can be JavaScript code. Then this JavaScript can be processed client-side. In your mind, you need to separate the two, and understand that when Liquid processes on the server, it knows nothing about JavaScript. It will simply process and output based on Liquid tags. It's your responsibility to ensure the output of the server that comes to the client is always valid JavaScript.
0

In your first snippet, pass cart.items as the variable items to the template:

{% include 'addItemToCartDetails', items: cart.items %}

In the file addItemToCartDetails.liquid template, modify the for loop statement accordingly:

{% for item in items %}

Comments

0

In your case, you can put this {% capture content %}{% include 'addItemToCartDetails' %}{% endcapture %} in your liquid code somewhere in your HTML probably hidden and append it to the element where you want it to appear like so.

success: function()
    {          
      var content = $("#addItemToCartDetails-wrapper").html();
      $("._second").html(content);
    }

Something like that. Hope that helps!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.