Работа с удаленными данными
Ваши привязываемые данные слишком велики или сложны для извлечения при загрузке страницы? У каждого варианта товара есть цена, на поиск которой уходит много времени? Поиск цен для разных вариантов непросмотренных товаров — пустая трата времени.
<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]" /> Попробуйте в действии: если вы выберете недоступный размер, вы не сможете добавить его в корзину.