Suppose I have the following json about the user reviews:
{
"reviewRating": 4,
"comment": "this is great"
}
Then I use amp-list to loop through the reviews.
<amp-list items="." single-item>
<template type="amp/mustache">
<!-- How can I render 4 star images here? -->
<span>Rating: {{reviewRating}}</span>
<p>{{comment}}</p>
</template>
</amp-list>
For the reviewRating, I want to render the same number of stars from reviewRating key/value to make a better look and feel. How can I do this in AMP?
This is possible by combining amp-bind
and amp-list
:
<amp-bind-macro id="classForRating" arguments="rating, index" expression="rating >= index ? 'star-full' : (rating >= (index - 0.5) ? 'star-half' : 'star-empty')" ></amp-bind-macro>
<amp-state id="state" src="rating.json"></amp-state>
<amp-list width="136" height="24" src="rating.json" single-item items="rating" noloading>
<template type="amp-mustache">
<div class="star-rating" aria-label="rating: {{.}}" [aria-label]="'rating: ' + state.rating">
<span [class]="classForRating(state.rating, 1)" class="star-empty"></span>
<span [class]="classForRating(state.rating, 2)" class="star-empty"></span>
<span [class]="classForRating(state.rating, 3)" class="star-empty"></span>
<span [class]="classForRating(state.rating, 4)" class="star-empty"></span>
<span [class]="classForRating(state.rating, 5)" class="star-empty"></span>
</div>
</template>
<div class="star-rating" placeholder>
<span class="star-empty"></span>
<span class="star-empty"></span>
<span class="star-empty"></span>
<span class="star-empty"></span>
<span class="star-empty"></span>
</div>
</amp-list>
The trick is to use the same endpoint for amp-state
and amp-list
. The AMP runtime's response caching ensures that this will only result in a single request. AMP bindings inside an amp-list will be evaluated when the list content is being rendered. This makes it possible to set the star values (via CSS classes) using amp-bind
.
To provide a good loading experience, I've also disabled the amp-list's default loading indicator using the noloading
attribute. Instead I'm using a placeholder
element showing empty stars while loading.
Here is a working version.