<!doctype html>
<html ⚡4email data-css-strict>
<head>
<meta charset="utf-8">
<script async src="https://cdn.ampproject.org/v0.js"></script>
<script async custom-element="amp-form" src="https://cdn.ampproject.org/v0/amp-form-0.1.js"></script>
<script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script>
<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js"></script>
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
<style amp4email-boilerplate>
body {
visibility: hidden
}
</style>
</head>
<body>
<amp-state id="selectedProduct">
<script type="application/json">
{
"src": "imageSrc",
"title": "ProductName",
"price": "400"
}
</script>
</amp-state>
<div class="container">
<amp-list width="500" height="500" layout="responsive" src="https://bounce.mailamp.in/similar-products" items="products">
<template type="amp-mustache">
<div class="product-item" on="tap:AMP.setState({
selectedProduct: {
src: {{src}},
title: {{title}},
price: {{price}}
}
})">
<amp-img class="product-image" width="100" height="100" src="{{src}}" alt="Product Image"></amp-img>
<p>{{title}}</p>
<p>Price: ₹{{price}}</p>
<form method="post" action-xhr="https://bounce.mailamp.in/add-to-cart">
<input type="hidden" name="src" [value]="selectedProduct.src">
<input type="hidden" name="title" [value]="selectedProduct.title">
<input type="hidden" name="price" [value]="selectedProduct.price">
<button type="submit" class="add-to-cart-button">Add to Cart</button>
</form>
</div>
</template>
</amp-list>
</div>
</body>
</html>
I'm working on an AMP for Email project and trying to implement an interactive product list using amp-list and amp-state. However, I'm facing issues with updating the state when a product is clicked. Below is the code snippet I'm using. I would appreciate any guidance on how to properly set this up for dynamic user interactions.
Specifically, I am unsure if I am using the AMP.setState correctly to update the selectedProduct state when a product is tapped. Any insights or corrections would be greatly appreciated!
There are a few orthogonal problems with the sample you provided:
Here's what the on
attribute on the <div>
looks like after the Mustache template is rendered:
tap:AMP.setState({
selectedProduct: {
src: https://bummer.in/cdn/shop/files/9000000664.2561_600x.jpg?v=1708346823,
title: Trunks - Disco82,
price: 599.00
}
})
This results in an error when you click on the div to trigger AMP's execution of the setState
call:
Error: Parse error on line 3:
... src: https://bummer.in/cdn/sho
-----------------------^
Expecting '-', '+', '*', '/', '%', '&&', '||', '<=', '<', '>=', '>', '!=', '==', '?', '.', ',', '[', '}', got ':'
You should see these errors in the JS console.
The values for src
and title
need to be quoted if the values are string literals. See examples at https://amp.dev/documentation/components/email/amp-bind#deep-merge-with-amp.setstate().
setState
call and the form submissionWhen you click on "Add to Cart", the form submission doesn't wait for the amp-bind
evaluation on the hidden form input elements to execute after the state changes when the outer div
is clicked. They happen in parallel in undefined order. As a result, what typically happens is that the first time you click on "Add To Cart", the form submits with the input fields set to the default values of the AMP state (src: imageSrc
and price: 400
) you set inside the <amp-state>
tag, as opposed to the values you intend to set using AMP.setState
.
What you can do is to ensure that the form is only submitted after the setState
happens. This can be done by
submit
buttonform.submit
action to trigger the form submission:If you give your <form>
element a DOM ID of form
, then you can do this:
<button on="tap:AMP.setState({
selectedProduct: {
src: '{{src}}',
title: '{{title}}',
price: '{{price}}',
}
}), form.submit" type="button" class="add-to-cart-button">
Add to Cart
</button>
You can debug AMP states by executing AMP.printState()
in the JS console, in the context of the AMP frame.
Even after fixing the above issues, your form submission doesn't work because it doesn't respond with the correct CORS headers:
Access to fetch at 'https://bounce.mailamp.in/add-to-cart?__amp_source_origin=https%3A%2F%2Fplayground.amp.dev' from origin 'https://playground.amp.dev' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.