One of my clients who has a Magento 2 site has a series of landing pages, setup to help users identify and purchase products a little more efficiently than simply browsing the category page.
If you just try to use the cart url generated from calling getAddToCartUrl(), without properly setting the options, you will get redirected back to the product page, with a message to the effect of “You need to choose options for your item.”
However, if you set some hidden inputs to for the options you want to select, it is possible to create a form that will add the product on a phtml template file.
For the purpose of this example, we are adding configurable product with a single attribute called ‘Size’ that is set to ‘Large’. So, this assumes that you have already added a main configurable product, individual child products, and correctly associated them with a product attribute.
Before you create the form, you need to find the correct Attribute ID and Attribute Value for the configurable product. Note that this is not the label, so not ‘Large’ or ‘Small’, but the numeric value of the attribute’s option.
Realistically, if you were using this in production, you would programatically determine the correct ID and value based on the label(see section below for one reason why). However, in the interest of keeping this example simple, we will just hard-code them to the form.
There are a few ways to find the option ID and value, including viewing html source on the front-end product page or backend. One way to find this is by logging into the Admin and going to System->Product->Attributes
From there, search for and click on the correct attribute, which for our example is ‘Size’. You can find the attribute ID by looking at the url. It will look something like this: /admin/catalog/product_attribute/edit/attribute_id/123/key/{YOUR_ADMIN_KEY}/
The Attribute ID is ‘123’.
Next, we need to find the Value of the ‘Large’ swatch, which you can find by viewing source code next to the swatch. You will see something like:
<input data-role="order" type="hidden" name="optionvisual[order][456]" value="0">
Or
<td class="swatch-col-456">
In the above, the value is ‘456’
So, now we know that the option ID is 123 and the option value is 456.
As noted above, there are other ways to find this info, including on the front end product page or when editing the product.
As noted in my notice above, this is a proof of concept only to demonstrate how the form should be setup. You should NOT actually load the product this way in a template and instead need to use dependency injection in your block or perhaps use a helper.
However, for the purposes of explaining how the configurable product options get added, this should work:
First generate the correct add to cart URL:
<?php $object_manager = \Magento\Framework\App\ObjectManager::getInstance(); $product_repository = $object_manager->get('\Magento\Catalog\Model\ProductRepository'); $product_object = $product_repository->get('BAN-000'); $cart_helper = $this->helper('Magento\Checkout\Helper\Cart'); $add_to_cart_url = $cart_helper->getAddUrl($product_object); ?>
Next, build the form. Note the hidden input we add for the size with a option/value of 123 and 456:
<form data-role="tocart-form" action="<?php echo $add_to_cart_url; ?>" method="post"> <?php echo $block->getBlockHtml('formkey')?> <input name="super_attribute[123]" type="hidden" value="456"> <button type="submit" title="Add to Cart" class="action primary tocart"> <span>Add to Cart</span> </button> </form>
Aside from the fact that you should not load the ObjectManager in this method, another possible issue is that the actual option value(456) can change if you adjust the settings of the attribute, such as by re-ordering it or moving it.
So, a more robust solution would dynamically pull the correct option ID and numeric Value based on the label or otherwise, rather than manually finding it.
You may also want to experiment with doing this in the background, upon success auto-opening the mini-cart, and/or redirecting to the cart. As it is, when you complete the above, it gets added, but the page reloads and does not indicate the product was added successfully.
I may update this post or add a new one to describe how to implement these features.
There are a few other ways of doing this, but I think this is likely the least complicated. Other things you may want to explore if the above does not work for you are using the Rest API, which you can do via JavaScript, although gets a bit complicated as you need to deal with logged in/logged out users, getting cart ID, and a few other things, so I don’t think doing it in a single JavaScript call may not be possible.
It is also possible to do it programaitcally via php code, like by creating your own add to cart url and if I were to do it another way, I think that would be my preference.
Do you have another method or changes to above? If so, please post or contact me!
Add a Comment