问题
I can't figure out how to overwrite data via AMP.setState.
I prepared an example:
- I have a list of products, output via amp-list.
- Each product has a 'quantity' value.
- Each product has two buttons: increase the quantity and decrease it.
<!DOCTYPE html>
<html amp lang="en">
<head>
<meta charset="utf-8" />
<script async src="https://cdn.ampproject.org/v0.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>
<title>Hello, AMPs</title>
<link rel="canonical" href="https://amp.dev/documentation/guides-and-tutorials/start/create/basic_markup/" />
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" />
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "NewsArticle",
"headline": "Open-source framework for publishing content",
"datePublished": "2015-10-07T12:02:41Z",
"image": ["logo.jpg"]
}
</script>
<style amp-boilerplate>
body {
-webkit-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
-moz-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
-ms-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
animation: -amp-start 8s steps(1, end) 0s 1 normal both;
}
@-webkit-keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
@-moz-keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
@-ms-keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
@-o-keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
@keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
</style>
<noscript>
<style amp-boilerplate>
body {
-webkit-animation: none;
-moz-animation: none;
-ms-animation: none;
animation: none;
}
</style>
</noscript>
</head>
<body>
<amp-state id="productData" src="https://alexkazakov.info/layout/amp-edit-array-state/data.json"></amp-state>
<h1>Welcome to the AMP web</h1>
<amp-list height="100" items="." src="https://alexkazakov.info/layout/amp-edit-array-state/data.json" single-item [src]="productData">
<template type="amp-mustache">
{{#items}}
<h3>{{name}}</h3>
<p>Quantity: {{quantity}}</p>
<button class="btn" on="tap:AMP.setState({productData: {items: {quantity: {{quantity}} + 1 } }})">Add +</button>
<button class="btn" on="tap:AMP.setState({productData: {items: {quantity: {{quantity}} - 1 } }})">Reduce -</button>
<hr />
{{/items}}
</template>
</amp-list>
</body>
</html>
Here is the JSON that is used there:
{ "items": [ { "id": "0", "name": "Item 1", "price": 1.99, "quantity": 18 }, { "id": "1", "name": "Item 2", "price": 2.99, "quantity": 15 }, { "id": "2", "name": "Item 3", "price": 0.99, "quantity": 33 } ], "total": "9.94", "discount": "0%" }
Codepen: https://codepen.io/alexandr-kazakov/pen/WNQWodZ
In my example, I overwrite the entire value of 'items', this is incorrect. I need that when you click on the button, the quantity of only one product decreases or increases. How do I do this?
回答1:
After many hours of thinking and trying I came to this decision:
I wrote two amp-bind-macro and completely overwrite the object.
In amp-bind-macro, I pass the index to determine which button was clicked. I searched a lot to see if the loop in amp-list has built-in indexes on each iteration, but I didn't find them. I have to take indexes from JSON.
I tried using the spread operator, but it doesn't seem to be supported in AMP. I had to do this, but the main thing is that I have solved my problem.
<!DOCTYPE html>
<html amp lang="en">
<head>
<meta charset="utf-8" />
<script async src="https://cdn.ampproject.org/v0.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>
<title>Hello, AMPs</title>
<link rel="canonical" href="https://amp.dev/documentation/guides-and-tutorials/start/create/basic_markup/" />
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1" />
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "NewsArticle",
"headline": "Open-source framework for publishing content",
"datePublished": "2015-10-07T12:02:41Z",
"image": ["logo.jpg"]
}
</script>
<style amp-boilerplate>
body {
-webkit-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
-moz-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
-ms-animation: -amp-start 8s steps(1, end) 0s 1 normal both;
animation: -amp-start 8s steps(1, end) 0s 1 normal both;
}
@-webkit-keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
@-moz-keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
@-ms-keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
@-o-keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
@keyframes -amp-start {
from {
visibility: hidden;
}
to {
visibility: visible;
}
}
</style>
<noscript>
<style amp-boilerplate>
body {
-webkit-animation: none;
-moz-animation: none;
-ms-animation: none;
animation: none;
}
</style>
</noscript>
</head>
<body>
<amp-state id="productData" src="https://alexkazakov.info/layout/amp-edit-array-state/data.json"></amp-state>
<h1>Welcome to the AMP web</h1>
<amp-list height="100" items="." src="https://alexkazakov.info/layout/amp-edit-array-state/data.json" single-item [src]="productData">
<template type="amp-mustache">
{{#items}}
<h3>{{name}}</h3>
<p>Quantity: {{quantity}}</p>
<amp-bind-macro id="addQuantity" arguments="argIndex" expression="productData.items.map((item, index, array) => index == argIndex ? {id: item.id, name: item.name, price: item.price, quantity: item.quantity + 1} : item )"></amp-bind-macro>
<amp-bind-macro id="reduceQuantity" arguments="argIndex" expression="productData.items.map((item, index, array) => index == argIndex ? {id: item.id, name: item.name, price: item.price, quantity: item.quantity - 1} : item )"></amp-bind-macro>
<button class="btn" on="tap:AMP.setState({productData: {items: addQuantity({{id}}) }})">Add +</button>
<button class="btn" on="tap:AMP.setState({productData: {items: reduceQuantity({{id}}) }})">Reduce -</button>
<hr />
{{/items}}
</template>
</amp-list>
</body>
</html>
Working demo: https://codepen.io/alexandr-kazakov/pen/ExVJQYL
来源:https://stackoverflow.com/questions/62003407/deep-merge-with-amp-setstate