Работа с удаленными данными
Ваши привязываемые данные слишком велики или сложны для извлечения при загрузке страницы? У каждого варианта товара есть цена, на поиск которой уходит много времени? Поиск цен для разных вариантов непросмотренных товаров — пустая трата времени.
<amp-state>
поддерживает загрузку удаленных данных через атрибут src
, который загружает JSON из конечной точки CORS. Эта загрузка выполняется один раз при загрузке страницы и полезна для обеспечения актуальности данных (особенно при загрузке из кеша).
Вы также можете привязать атрибут src
к элементу <amp-state>
. Это означает, что действие пользователя может инициировать загрузку удаленных данных JSON в привязываемое состояние страницы.
Загрузка имеющихся размеров рубашки
Давайте воспользуемся возможностью извлечения удаленных данных, чтобы получить цены вариантов товаров, представленных в нашей выборке. Наш сервер разработки Express.js в app.js
уже имеет конечную точку /shirts/sizesAndPrices?shirt=<sku>
которая, учитывая варианты рубашки, возвращает доступные размеры и цену для каждого размера. Он отправляет ответ с искусственной задержкой в одну секунду для имитации задержки в сети.
Запрос | Ответ |
---|---|
GET /shirts/sizesAndPrices?sku=1001 |
{"1001: {"sizes": {"XS": 8.99, "S" 9.99}}} |
Подобно данным JSON внутри элементов <amp-state>
, удаленные данные, возвращаемые из этих выборок, объединяются и доступны в атрибуте id
элемента. Например, к данным, возвращенным из приведенного выше примера ответа, можно получить доступ в выражении:
Выражение | Результат |
---|---|
shirts['1001'].sizes['XS'] |
8.99 |
Привяжите данные
Теперь давайте применим это в нашем примере интернет-магазина. Сначала давайте извлечем данные рубашки при выборе нового варианта. Добавьте привязку [src]
к нашему элементу amp-state#shirts
:
<!-- When `selected.sku` changes, update the `src` attribute and fetch
JSON at the new URL. Then, merge that data under `id` ("shirts"). -->
<amp-state
id="shirts"
[src]="'/shirts/sizesAndPrices?sku=' + selected.sku"
></amp-state>
Укажите отсутствующие размеры
Далее давайте четко пометим отсутствующие размеры как таковые для данного варианта товара. CSS-класс "unavailable"
перечеркивает элемент диагональной линией — мы можем добавить его в соответствующие отсутствующим размерам элементы, размещенные внутри amp-selector
:
<amp-selector name="size">
<table>
<tr>
<!-- If 'XS' size is available for selected SKU, return empty string.
Otherwise, return 'unavailable'. -->
<td [class]="shirts[selected.sku].sizes['XS'] ? '' : 'unavailable'">
<div option="XS">XS</div>
</td>
<td [class]="shirts[selected.sku].sizes['S'] ? '' : 'unavailable'">
<div option="S">S</div>
</td>
<td [class]="shirts[selected.sku].sizes['M'] ? '' : 'unavailable'">
<div option="M">M</div>
</td>
<td [class]="shirts[selected.sku].sizes['L'] ? '' : 'unavailable'">
<div option="L">L</div>
</td>
<td [class]="shirts[selected.sku].sizes['XL'] ? '' : 'unavailable'">
<div option="XL">XL</div>
</td>
</tr>
</table>
</amp-selector>
Теперь перезагрузите страницу и попробуйте ее в работе. Выбор нового варианта товара (цвета рубашки) приведет к вычеркиванию отсутствующих размеров (после небольшой задержки).
Укажите начальные состояния
Есть небольшая проблема — что делать с рубашкой черного цвета, т. е. цвета, выбранного по умолчанию? Нам нужно будет добавить данные о размерах и цене черной рубашки в amp-state#shirts
, поскольку amp-bind
запускается только в ответ на явные действия пользователя:
<amp-state id="shirts" [src]="'/shirts/sizesAndPrices?sku=' + selected.sku">
<script type="application/json">
{
"1001": {
"color": "black",
"image": "./shirts/black.jpg",
"sizes": {
"XS": 8.99,
"S": 9.99
}
},
<!-- ... -->
Нам также нужно обновить состояние по умолчанию соответствующих элементов:
<amp-selector name="size">
<table>
<tr>
<!-- If 'XS' size is available for selected SKU, return empty string.
Otherwise, return 'unavailable'. -->
<td [class]="shirts[selected.sku].sizes['XS'] ? '' : 'unavailable'">
<div option="XS">XS</div>
</td>
<td [class]="shirts[selected.sku].sizes['S'] ? '' : 'unavailable'">
<div option="S">S</div>
</td>
<!-- Add the 'unavailable' class to the next three <td> elements
to be consistent with the available sizes of the default SKU. -->
<td
class="unavailable"
[class]="shirts[selected.sku].sizes['M'] ? '' : 'unavailable'"
>
<div option="M">M</div>
</td>
<td
class="unavailable"
[class]="shirts[selected.sku].sizes['L'] ? '' : 'unavailable'"
>
<div option="L">L</div>
</td>
<td
class="unavailable"
[class]="shirts[selected.sku].sizes['XL'] ? '' : 'unavailable'"
>
<div option="XL">XL</div>
</td>
</tr>
</table>
</amp-selector>
Переменные цены на рубашки
Теперь, когда мы правильно отображаем доступные размеры, давайте удостоверимся, что отображается правильная цена.
Наш магазин AMPPAREL отличается тем, что цена на рубашку зависит от цвета и размера. Это означает, что нам нужна новая переменная для отслеживания выбранного пользователем размера. Добавьте новое действие к нашему элементу размера amp-selector
:
<!-- When an element is selected, set the `selectedSize` variable to the
value of the "option" attribute of the selected element. -->
<amp-selector
name="size"
on="select:AMP.setState({selectedSize: event.targetOption})"
></amp-selector>
Обратите внимание, что мы не инициализируем значение selectedSize
через элемент amp-state#selected
. Это потому, что мы намеренно не предоставляем выбранный размер по умолчанию и вместо этого хотим заставить пользователя выбирать размер.
AMP.setState()
может использоваться для определения новых переменных в дополнение к изменению существующих. Выражения оценят неопределенные переменные в null
. Добавьте новый элемент <span>
обертывающий ценовую метку, и измените текст по умолчанию на «---», поскольку размер по умолчанию не выбран.
<h6>
PRICE :
<!-- Display the price of the selected shirt in the selected size if available.
Otherwise, display the placeholder text '---'. -->
<span [text]="shirts[selected.sku].sizes[selectedSize] || '---'">---</span>
</h6>
И у нас правильные цены! Попробуйте это.
Условно-активная кнопка
Мы почти закончили! Давайте отключим кнопку «Добавить в корзину», когда выбранный размер недоступен:
<!-- Disable the "ADD TO CART" button when:
1. There is no selected size, OR
2. The available sizes for the selected SKU haven't been fetched yet
-->
<input
type="submit"
value="ADD TO CART"
disabled
class="mdl-button mdl-button--raised mdl-button--accent"
[disabled]="!selectedSize || !shirts[selected.sku].sizes[selectedSize]"
/>
Попробуйте в действии: если вы выберете недоступный размер, вы не сможете добавить его в корзину.