We are using the software of Odoo 12 for enterprises.
We want to duplicate the behaviour of the add to cart button on the product pages. So we want to add a button on a different page and when you click the button you add a product to your cart and get redirected to your cart. The product is hardcoded to that button.
This is the form used on the product page template:
<form t-if="product._is_add_to_cart_possible()" action="/shop/cart/update" method="POST">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<div class="js_product js_main_product">
<t t-placeholder="select">
<input type="hidden" class="product_id" name="product_id" t-att-value="product_variant.id"/>
<input type="hidden" class="product_template_id" name="product_template_id" t-att-value="product.id"/>
<t t-if="first_possible_combination" t-call="sale.variants">
<t t-set="ul_class" t-value="'flex-column'"/>
<t t-set="parent_combination" t-value="None"/>
</t>
<t t-else="">
<ul class="d-none js_add_cart_variants" t-att-data-attribute_exclusions="{'exclusions: []'}"/>
</t>
</t>
<t t-call="website_sale.product_price"/>
<p t-if="True" class="css_not_available_msg alert alert-warning">This combination does not exist.</p>
<a role="button" id="add_to_cart" class="btn btn-primary btn-lg mt8 js_check_product a-submit" href="#">Add to Cart</a>
</div>
</form>
The info of our product: product.id = 135
and product_template.id = 83
.
I've found that the javascript responsible for the adding to the cart is called using: /web/content/.../.../web.assets_frontend.js
. This is a very large file but you can check an example here: file.
Which qweb/form/js/... should I add on my custom page to add a product to my cart?
Thanks for any help, I've been stuck on this for a long time!
Edit: As @Philippe Pageau pointed out I can use some code to get the correct product already. I've tried implementing it with the form using this code (the simplest version of the form I can think of):
<t t-set="products" t-value="request.env['product.product'].search([['id', '=', 135]])"/>
<t t-foreach="products" t-as="product">
<form action="/shop/cart/update" method="POST">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" class="product_id" name="product_id" value="135"/>
<input type="hidden" class="product_template_id" name="product_template_id" value="83"/>
<a role="button" id="add_to_cart" class="btn btn-primary btn-lg mt8 js_check_product a-submit" href="#">Add to Cart</a>
</form>
</t>
But this does nothing, what am I missing?
Edit2:
Thanks to @Adan Cortes we are further now but there is still 1 problem.
Now when the user clicks on a button the products gets added to the cart with a specific quantity.
This is my code now:
<t t-set="products" t-value="request.env['product.product'].search([['id', '=', 135]])"/>
<t t-foreach="products" t-as="product">
<div id="product_detail" class="oe_website_sale">
<form action="/shop/cart/update" method="POST">
<h4 t-esc="product.name"/>
<h6 t-esc="product.price"/>
<input class="form-control" data-min="1" name="add_qty" value="1"/>
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" class="product_id" name="product_id" value="135"/>
<a role="button" id="add_to_cart" class="btn btn-primary btn-lg mt8 js_check_product a-submit" href="#">Add to Cart</a>
</form>
</div>
</t>
But these are my final problems:
This code doesn't show the product price. <h6 t-esc="product.price"/>
displays 0.00
. So how can I display the price?
Finally is it possible to add multiple products at once using only 1 button and form?
The following code works:
<div id="product_detail" class="oe_website_sale">
<form action="/shop/cart/update" method="POST">
<input type="hidden" name="csrf_token" t-att-value="request.csrf_token()"/>
<input type="hidden" class="product_id" name="product_id" value="135"/>
<a role="button" id="add_to_cart" class="btn btn-primary btn-lg mt8 js_check_product a-submit" href="#">Add to Cart</a>
</form>
</div>
But beware that using the database id makes your module unusable elsewhere. You better use xmlids.
The relevant JavaScript you were missing is at:
<path_to_v12>/addons/website_sale/static/src/js/website_sale.js
135 sAnimations.registry.WebsiteSale = sAnimations.Class.extend(ProductConfiguratorMixin, {
136 selector: '.oe_website_sale',
137 read_events: {
138 'change form .js_product:first input[name="add_qty"]': '_onChangeAddQuantity',
139 'mouseup .js_publish': '_onMouseupPublish',
140 'touchend .js_publish': '_onMouseupPublish',
141 'change .oe_cart input.js_quantity[data-product-id]': '_onChangeCartQuantity',
142 'click .oe_cart a.js_add_suggested_products': '_onClickSuggestedProduct',
143 'click a.js_add_cart_json': '_onClickAddCartJSON',
144 'click .a-submit': '_onClickSubmit',
145 'change form.js_attributes input, form.js_attributes select': '_onChangeAttribute',
146 'mouseup form.js_add_cart_json label': '_onMouseupAddCartLabel',
147 'touchend form.js_add_cart_json label': '_onMouseupAddCartLabel',
148 'click .show_coupon': '_onClickShowCoupon',
149 'submit .o_website_sale_search': '_onSubmitSaleSearch',
150 'change select[name="country_id"]': '_onChangeCountry',
151 'change #shipping_use_same': '_onChangeShippingUseSame',
152 'click .toggle_summary': '_onToggleSummary',
153 'click input.js_product_change': 'onChangeVariant',
154 'change .js_main_product [data-attribute_exclusions]': 'onChangeVariant',
155 },
and <path_to_v12>/addons/website_sale/static/src/js/website_sale_tracking.js
5 sAnimations.registry.websiteSaleTracking = sAnimations.Class.extend({
6 selector: '.oe_website_sale',
7 read_events: {
8 'click form[action="/shop/cart/update"] a.a-submit': '_onAddProductIntoCart',
9 'click a[href="/shop/checkout"]': '_onCheckoutStart',
10 'click div.oe_cart a[href^="/web?redirect"][href$="/shop/checkout"]': '_onCustomerSignin',
11 'click form[action="/shop/confirm_order"] a.a-submit': '_onOrder',
12 'click form[target="_self"] button[type=submit]': '_onOrderPayment',
13 },
Edited to add
The form data is processed and dispatched by the following controller:
<path_to_v12>/addons/website_sale/controllers/main.py
414 @http.route(['/shop/cart/update'], type='http', auth="public", methods=['POST'], website=True, csrf=False)
415 def cart_update(self, product_id, add_qty=1, set_qty=0, **kw):
416 """This route is called when adding a product to cart (no options)."""
418 sale_order = request.website.sale_get_order(force_create=True)
419 if sale_order.state != 'draft':
420 request.session['sale_order_id'] = None
421 sale_order = request.website.sale_get_order(force_create=True)
422
423 product_custom_attribute_values = None
424 if kw.get('product_custom_attribute_values'):
425 product_custom_attribute_values = json.loads(kw.get('product_custom_attribute_values'))
426
427 no_variant_attribute_values = None
428 if kw.get('no_variant_attribute_values'):
429 no_variant_attribute_values = json.loads(kw.get('no_variant_attribute_values'))
430
431 sale_order._cart_update(
432 product_id=int(product_id),
433 add_qty=add_qty,
434 set_qty=set_qty,
435 product_custom_attribute_values=product_custom_attribute_values,
436 no_variant_attribute_values=no_variant_attribute_values
437 )
438 return request.redirect("/shop/cart")