Shopify liquid, add multiple products to cart - shopify

So I used shopify liquid to add a collection page, in this collection page, there is multiple products. A button named "Add all" will add all products from this collection to shopping cart when click.
How can I achieve this in shopify liquid language? Or how many way we can do this?
Also, when I tried to use this from the official doc
jQuery.post('/cart/add.js', {
quantity: 1,
id: 10911378372,
properties: {
'First name': 'Caroline'
}
}).done(function() {
console.log("second success");
})
.fail(function(err) {
if(err.statusText !== 'OK'){
console.log("error", err);
}
})
.always(function() {
console.log("finished");
});
even the statusText is Ok, it falls into the fail block and I don't know why.

Well for add multiple items to cart is neccesary a recursive loop.
I did a code for this issue, feel free for use:
github link
the sample is in the begin function:
//IF PROPERTIES IS EMPTY ONLY SET FALSE
MGUtil.data = [
{"id":"12345","qty":2,"properties":{"data1":"1"}},
{"id":"34567","qty":3,"properties":{"data2":"1"}},
{"id":"67892","qty":1,"properties":{"data3":"1"}},
{"id":"23456","qty":6,"properties":false}
]; // ADD 4 ITEMS
MGUtil.total = MGUtil.data.length;
MGUtil.action = 'add';
MGUtil.recursive();//EXECUTE

You would actually do this with a set of AJAX calls. You can only add one item to the cart at a time. See the AJAX API help.
Then you'd use .liquid to get the default variant id for each displayed product either into a list or, what I generally do, as something like:
<div data-variant="{{ product.selected_or_first_available_variant }}">
...
</div>
see: https://help.shopify.com/themes/liquid/objects/product#product-selected_or_first_available_variant to see if that would be sufficient
and then your button script would gather the variant ids and add them one-by-one to the cart.
There is an example here of adding an item to the cart with JQuery

Related

Passing {{raw}} variable to snippet - Shopify

I have created a simple AJAX request which feeds back to the header template. However, I can not seem to be able to do any of the following assign, capture, render, include.
<script id="CartPopover" type="text/x-handlebars-template">
{% raw %}
{{#items}}
{% render "cart-item", item: item %}
{{/items}}
{% endraw %}
</div>
Update
I am attempting to update the sliding side cart on the website when a product is added to cart. Please see the ajax, /cart/add.js success
function below.
var showCartNotificationPopup = function (product) {
var addedQuantity = parseInt($('.quantity__input', this.$container).val());
$.get("/cart.json", function (data) {
var cart_items = data.items
$.each(cart_items, function (index, item) {
item.minus_quatinty = item.quantity - 1;
item.formatPrice = Shopify.formatMoney(item.final_price)
})
cart = {
items: data.items
}
$("#side-cart-container").find(".item").detach();
$("#CartOuter table tbody").prepend(template(cart));
console.log(cart);
$("#side-cart-container").addClass("visible");
});
clearTimeout(popoverTimer);
}
You are misunderstanding how Shopify works. Liquid code is parsed once by Shopify when a page is loaded. Shopify creates a huge string of HTML, CSS and JS and dumps it into the browser.
Once you are in the land of Javascript, you no longer play with Liquid. Instead, you play with data. So, if you want to update the cart, you use Javascript. If you want to know what is in the cart, you use Javascript. If you want to re-render the contents of the cart, you replace the DOM you no longer like with new DOM. Use Javascript templates for this.
No amount of Liquid in your JS will help you except during render time. At render time, you can certainly build and fill a Javascript data structure with data from Liquid.

Vue.js: binding select boxes, but don't want to ajax all the options

Good day. I'm using Vue.js to render an arbitrary number of select elements from the data in a component.
Here's sample JSON data that indicates there are two select elements, each with one or more options.
{
"dropdowns":[
{
"cd":"UG9ydGZvbGlv",
"formname":"sp_filter_UG9ydGZvbGlv",
"nm":"Portfolio",
"selected":"1a",
"options":[
{
"cd":"1a",
"val":"Option 1A"
}
]
},
{
"cd":"UHJvZHVjdCBOYW1l",
"formname":"sp_filter_UHJvZHVjdCBOYW1l",
"nm":"Product Name",
"selected":"2b",
"options":[
{
"cd":"2a",
"val":"Option 2A"
},
{
"cd":"2b",
"val":"Option 2B"
}
]
}
]
}
Here's the template HTML:
<form>
<div v-for="dropdown in dropdowns">
<div v-if="dropdown.availableToView">
<h4>{{dropdown.nm}}</h4>
<select v-model="dropdown.selected" v-on:change="triggerUpdate">
<option value="">(Make a selection)</option>
<option v-for="option in dropdown.options" :value="option.cd">{{option.val}}</option>
</select>
</div>
</div>
</form>
So far so good.
I've got the data loading and Vue is building the dropdowns.
When the user changes any select box (remember there can be an arbitrary number of them), the trigger action needs to submit ALL of the elements in the form via ajax. It sounds like the most correct option is to bind the form fields to the underlying component data, as I've done.
My triggerUpdate looks like this:
methods: {
triggerUpdate: function() {
axios({
method: "post",
url: actionURL,
data: this.dropdowns
})
.then(response => (this.data = response));
}
}
...but this submits the entire dropdowns data element, including all of the options in each select box. It's unnecessary to send all of the options in. I just want to send each field name along with its selected option (i.e. the "value").
I know i could serialize the whole form and make that my ajax payload. But that seems to be making an "end run" around Vue.js. Everyone talks about having your form fields bound to the Vue model...is it then correct to basically ignore the model when making an ajax request whose purpose is to then update the model?
I'm relatively new to Vue.js so I'd appreciate help with what I'm overlooking here. How should I go about sending in the data from the form (a) while using proper Vue.js binding and (b) without sending extraneous data?
Thanks for your time.
If you need to post only the selected values, and you store those in each dropdown's selected property, the sensible approach seems to be just mapping it to a simple array of name/value objects.
Try this (it assumes the name of each field is the formname property, if it isn't you can just replace it):
var submitData = this.dropdowns.map((dropdown) => {
return { name: dropdown.formname, value: dropdown.selected };
});
Then you send submitData in your ajax request.

Has Ajaxsubmit been renamed in Stencil from Blueprint? I need to add multiple sizes of product with seperate quantity boxes to cart on BigCommerce

TLDR: has the ajaxsubmit url parameter been renamed in Stencil, or is there a better way to add multiple sizes with different quantities to the cart quickly?
I need to have separate quantity boxes for each size of a product so customers can order for sports teams. I have been able to make this format appear on the frontend by using this code in templates/components/products/set-select.html:
{{#if display_name '==' 'Size'}}
{{#each values}}
<label>{{label}}</label>
<input class="size-quantity" type="tel" name="{{id}}">
{{/each}}
<script>
sizeattributeid = {{id}};
</script>
{{/if}}
I have also created a separate 'Add Sizes to Cart' button that fires a function looping through each .size-quantity box to collect the 'name' and 'val' of each one so I can submit it to the cart.
My first thought was to do this via an ajax request with jQuery like this:
productid = jQuery('input[name="product_id"]').val();
jQuery('.size-quantity').each(function() {
qty_value = jQuery(this).val();
sizeattributevalue = jQuery(this).attr('name');
$.ajax({
type: 'GET',
url: cartUrl+'?action=add&product_id='+productid+'&qty[]=qty_value&attribute['+sizeattributeid+']='+sizeattributevalue+'&ajaxsubmit=1&fastcart=1',
success: function(data) {
//parse bigcommerce html reponse
var obj = JSON.parse($(data).html());
//success property = true if item was added successfully
if (obj.success) {
console.log('yay!');
} else {
console.log('fail!');
}
}
});
});
And I have been able to get the crafted URL to add a product to the cart if I paste the generated url into the browser...but I have not been able to with ajax. It seems the ajaxsubmit part of their code does not work with Stencil the way that it worked with Blueprint.
Has this code been renamed? My only alternative to this has been to hide the select box for size and the box for quantity, and then on submit loop through each size and have the quantity box fill in with the desired quantity and submit the form...but that is slow and the only way I've been able to get that to work is by spacing out my requests 600ms at a time, an unacceptable wait.

Bigcommerce Stencil SKU number on Category pages

I currently see {{product.sku}} which is tied to product page.
I need to show sku number on category/search pages but there is not global property.
Editing templates > components > products > card.html
If you know of any solution or point me in the right direction, that would be a help.
thanks you in advance :)
Here is an example, tailored to your site specifically, on how you can load the SKU from each product page, and then insert it on the category page. This code should go on the category page. It is meant just as an example, you may have to modify it to work on your site.
// For Each Product...
$('.product').each(function(i) {
// Get the product URL
var url = $('> article > figure > a', this).attr('href'); // http://screencast.com/t/qBgwszhhpFiz
// Perform GET
getProductSKU(url).then(function(sku) {
console.log(sku);
// do something with the sku
// such as append it to the product, maybe above the 'add to cart button'
});
});
/**
* Performs HTTP Get to a given product page
* and returns the SKU on that page.
* #param url <string> - The product URL to GET
* #return Promise - Resolved with product SKU on success.
*/
function getProductSKU(url) {
return new Promise(function(resolve, reject) {
$.ajax({
url: url,
type:'GET',
success: function(data){
resolve($(data).find('#sku-value').text()); //Return the SKU - http://screencast.com/t/zlCAftmekgp
},
error: reject
});
});
}
Links:
http://screencast.com/t/qBgwszhhpFiz
http://screencast.com/t/zlCAftmekgp
You can do an ajax load() call to pull in this information to the page you need it on, but there's not currently a helper or data exposed by the product card to support this.

Bigcommerce Stencil access more subcategory levels on category page

Is there any way to access more subcategory levels on the category page? Currently, in the context of the category on a category page, there exists a subcategories attribute which lists the immediate children of the current category. Is there any way to have the system return the subcategories of each of those subcategories as well?
I was hoping this could be done via front-matter or some setting in the control panel?
There isn't a way with the existing front-matter or store settings. It would need to be added by BigCommerce as a new feature.
Been there! And as answered be Alyss there's no way to do that straight from the server.
That being said you can always get it done through an AJAX call to the subcategory url and take just what you need from there to finish populating your category page with subcategory products.
First in the category template file I added an empty element with the data I needed to make the call:
<div class="nested container">
<main data-ajax-url="{{url}}" class="product-listing-container"></main>
</div>
Then I added this method to the theme/category.js file and called it inside the loaded method called on template load.
getSubcategoryProducts() {
$('[data-ajax-url]').each((index, el) => {
const $this = $(el);
const thisCatURL = $this.data('ajax-url');
let $thisCatProducts;
$.ajax({
url: thisCatURL,
type: 'GET',
dataType: 'html',
async: true,
}).done((data) => {
$thisCatProducts = $(data).find('#product-listing-container').html();
$this.html(thisCatProducts);
});
});
}
I'm sure there are better ways to do it, probably through the Stencil Utils API but I'm still trying to get a grasp of it as there's close to zero documentation on that.
Good coding!