How to AJAX load page content
This tutorial outlines the steps required to dynamically refresh page content without the need to reload the entire page. Neto already does this when selecting product variations but this can be expanded to include other webstore content as well.
This tutorial will focus on refreshing a small static part of the product page. Looking to AJAX load a large block of content - to say, create an infinite scrolling page? You may find the B@SE implementation for this limiting, instead consider using jQuery ajax() or the JS Fetch API.
For the purposes of this tutorial we will be taking the product reviews and adding pagination so that all reviews on a product can be viewed instead of the default limit. To do so, we will need to create a new theme template via SFTP. Don't have SFTP access, read this first.
Step 1 - Setup your theme templates
Connect to your webstore server via SFTP and navigate to your themes /templates/products/includes
folder. Create a new file in the includes
folder called ajax_reviews.template.html
. Once the file exists, open it in your preferred code editor or via the Neto control panels 'Webstore Templates' settings.
Next, locate the product_information.template.html
file in the same folder and open it.
Files or code not where they should be? You might be running a custom or older theme. In this case, start at the main product template.html
file and work your way through each includes template until you have found the corresponding code in your theme. Need a refresher on our theme folder structure? refer to our Introduction Guide.
Step 2 - Copy over the code to be AJAX loaded
In the product_information
template, locate the existing product_reviews
thumb_list code block - highlighted here in our default Skeletal Theme. Cut out the whole thumb_list and paste it into your new ajax_reviews
template.
Where the thumb_list code was in the product_information
template add the following code:
[%load_ajax_template id:'_ajax_reviews' type:'item' template:'ajax_reviews' preload:'1' tmpl_sku:'[@current_sku@]' tmpl_preview:'y'/%]
If you were to save both templates and view your webstore, the product page should look exactly the same. Except now the review content is coming from the ajax_reviews
template, not the product_information template. For a full rundown of the above code refer to our load_ajax_template function documentation.
Step 3 - Setup the AJAX refresh trigger
Now that the product reviews can be AJAX loaded, we need to add a trigger to get to the next or previous set of reviews. This will be done with a set of pagination links generated by the [%paging%]
function. In the ajax_reviews
template, add a *footer param
to the thumb_list and add the following code:
[%if [@total_results@] > 5 %]
<div class="row">
<div class="col-12">
<hr aria-hidden="true"/>
<nav aria-label="Page navigation">
<ul class="pagination justify-content-center">
[%paging limit:'3'%]
[%param *previous_page%]<li class="page-item"><a class="page-link" href="#reviews" onclick="$.load_ajax_template('_ajax_reviews',{showloading: '1', ajax_reviews_page: '[@page@]',sku: '[@sku@]'})"><i class="fa fa-chevron-left"></i></a></li>[%/param%]
[%param *goback_pages%]<li class="page-item"><a class="page-link" href="#reviews" onclick="$.load_ajax_template('_ajax_reviews',{showloading: '1', ajax_reviews_page: '[@page@]',sku: '[@sku@]'})">[@page@]</a></li>[%/param%]
[%param *current_page%]<li class="page-item active"><a class="page-link" href="#reviews" onclick="$.load_ajax_template('_ajax_reviews',{showloading: '1', ajax_reviews_page: '[@page@]',sku: '[@sku@]'})">[@page@]</a></li>[%/param%]
[%param *gonext_pages%]<li class="page-item"><a class="page-link" href="#reviews" onclick="$.load_ajax_template('_ajax_reviews',{showloading: '1', ajax_reviews_page: '[@page@]',sku: '[@sku@]'})">[@page@]</a></li>[%/param%]
[%param *next_page%]<li class="page-item"><a class="page-link" href="#reviews" onclick="$.load_ajax_template('_ajax_reviews',{showloading: '1', ajax_reviews_page: '[@page@]',sku: '[@sku@]'})"><i class="fa fa-chevron-right"></i></a></li>[%/param%]
[%/paging%]
</ul>
</nav>
<hr aria-hidden="true"/>
</div>
</div>
[%/if%]
The above code triggers the $.load_ajax_template()
function when one of the pagination links is clicked/pressed. This function passes the corresponding pagination 'page' (to tell the AJAX template to either go back or forward through the reviews) along with the product SKU (if you don't pass the SKU back to the AJAX template it will lose scope and not know which product reviews to display).
The showloading: '1'
option tells the template to create a loading overlay whenever the AJAX template is actively loading. For a full rundown of the $.load_ajax_template()
function, refer to our load_ajax_template documentation.
We now have way to trigger the AJAX refresh and pass the new pagination value through, but the reviews thumb_list is not checking it. To change this, add the following code just under the thumb_list function declaration:
[%param pgnum%][%if [@ajax_reviews_page@]%][@ajax_reviews_page@][%else%]1[%/if%][%/param%]
This code tells the thumb_list to check for the ajax_reviews_page
value that we have previously set. If that value does not exist we should assume this is the first page of reviews. This pgnum
is then passed to the thumb_list as the current page number.
Step 4 - Review and test
With the above changes made you should now be able to paginate through reviews on your webstore product pages. Ensure all templates have been saved (if you are working out of a code editor, ensure these are pushed back to the webstore server via SFTP). Your product_information
template should look something like this:
...
[%if [@config:show_product_reviews@]%]
<div class="tab-pane" id="reviews" role="tabpanel" aria-labelledby="tabReviews">
<div class="card">
<div class="card-header py-1 px-2" id="headingReviews">
<h5 class="mb-0">
<button class="btn btn-link btn-block text-left" type="button" data-toggle="collapse" data-target="#accordionReviews" aria-expanded="true" aria-controls="accordionReviews">
Reviews
[%set [@data:ratings-count@] = 1 /%]
[%while [@data:ratings-count@] <= [@data:rating@]%]
[%set [@data:ratings-count@] = [@data:ratings-count@]+1 /%]
<i class="fas fa-star" aria-hidden="true"></i>
[%/while%]
[%while [@data:ratings-count@] <= 5%]
[%set [@data:ratings-count@] = [@data:ratings-count@]+1 /%]
<i class="far fa-star" aria-hidden="true"></i>
[%/while%]
</button>
</h5>
</div>
<div id="accordionReviews" class="collapse" aria-labelledby="headingReviews">
<div class="card-body p-md-0">
<!-- reviews thumb_list -->
[%load_ajax_template id:'_ajax_reviews' type:'item' template:'ajax_reviews' preload:'1' tmpl_sku:'[@current_sku@]' tmpl_preview:'y'/%]
[%if [@reviews@] > 0%]
<p>
<a class="btn btn-default" href="[%URL page:'account' type:'write_review' qs:'item=[@SKU@]'%][%/URL%]"><i class="far fa-edit"></i> Write a product review</a>
</p>
[%else%]
<h4>Be The First To Review This Product!</h4>
<p>Help other [@config:company_name@] users shop smarter by writing reviews for products you have purchased.</p>
<p><a class="btn btn-default" href="[%URL page:'account' type:'write_review' qs:'item=[@SKU@]'%][%/URL%]"><i class="far fa-edit"></i> Write a product review</a></p>
[%/if%]
</div>
</div>
</div>
</div>
[%/if%]
...
While your ajax_reviews
template should look something like this:
[%thumb_list type:'product_reviews' limit:'5'%]
[%param pgnum%][%if [@ajax_reviews_page@]%][@ajax_reviews_page@][%else%]1[%/if%][%/param%]
[%param filter_1%][@SKU@][%/param%]
[%param *body%]
<div itemprop="review" itemscope itemtype="http://schema.org/Review">
<meta itemprop="itemReviewed" content="[@name@]">
<meta itemprop="image" content="[%asset_url type:'product' thumb:'thumb' id:'[@SKU@]'%][%param default%][%cdn_asset html:'0' library:'images'%]default_product.gif[%/cdn_asset%][%end param%][%/asset_url%]">
<blockquote>
<h4 itemprop="name">[%nohtml%][@title@][%/nohtml%]</h4>
<div>
<strong>
[%if [@reviewname@]%]
By: <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">[%nohtml%][@reviewname@][%/nohtml%]</span></span> on
[%/if%]
<meta itemprop="datePublished" content="[%FORMAT type:'date'%][@insert_date@][%/FORMAT%]">[%FORMAT type:'date'%][@insert_date@][%/FORMAT%]
</strong>
</div>
<span itemprop="description">[%nohtml%][@review@][%/nohtml%]</span><br />
<div itemprop="reviewRating" itemscope itemtype="http://schema.org/Rating">
<meta itemprop="worstRating" content = "1">
<meta itemprop="ratingValue" content = "[@score@]">
<meta itemprop="bestRating" content = "5">
</div>
[%set [@data:ratings-count@] = 1 /%]
[%while [@data:ratings-count@] <= [@data:score@]%]
[%set [@data:ratings-count@] = [@data:ratings-count@]+1 /%]
<i class="fas fa-star"></i>
[%/while%]
[%while [@data:ratings-count@] <= 5%]
[%set [@data:ratings-count@] = [@data:ratings-count@]+1 /%]
<i class="far fa-star"></i>
[%/while%]
([@score@])
[%if [@review_response@]%]
<br /><br />
<blockquote>
<span class="review_response text-muted"><strong><i>[@config:website_name@] Response</i></strong><br /> [%nohtml%][@review_response@][%/nohtml%]</span>
</blockquote>
[%/if%]
</blockquote>
</div>
[%/param%]
[%param *footer%]
[%if [@total_results@] > 5 %]
<div class="row">
<div class="col-12">
<hr aria-hidden="true"/>
<nav aria-label="Page navigation">
<ul class="pagination justify-content-center">
[%paging limit:'3'%]
[%param *previous_page%]<li class="page-item"><a class="page-link" href="#reviews" onclick="$.load_ajax_template('_ajax_reviews',{showloading: '1', ajax_reviews_page: '[@page@]',sku: '[@sku@]'})"><i class="fa fa-chevron-left"></i></a></li>[%/param%]
[%param *goback_pages%]<li class="page-item"><a class="page-link" href="#reviews" onclick="$.load_ajax_template('_ajax_reviews',{showloading: '1', ajax_reviews_page: '[@page@]',sku: '[@sku@]'})">[@page@]</a></li>[%/param%]
[%param *current_page%]<li class="page-item active"><a class="page-link" href="#reviews" onclick="$.load_ajax_template('_ajax_reviews',{showloading: '1', ajax_reviews_page: '[@page@]',sku: '[@sku@]'})">[@page@]</a></li>[%/param%]
[%param *gonext_pages%]<li class="page-item"><a class="page-link" href="#reviews" onclick="$.load_ajax_template('_ajax_reviews',{showloading: '1', ajax_reviews_page: '[@page@]',sku: '[@sku@]'})">[@page@]</a></li>[%/param%]
[%param *next_page%]<li class="page-item"><a class="page-link" href="#reviews" onclick="$.load_ajax_template('_ajax_reviews',{showloading: '1', ajax_reviews_page: '[@page@]',sku: '[@sku@]'})"><i class="fa fa-chevron-right"></i></a></li>[%/param%]
[%/paging%]
</ul>
</nav>
<hr aria-hidden="true"/>
</div>
</div>
[%/if%]
[%/param%]
[%param *ifempty%]
[%/param%]
[%/thumb_list%]
Not sure about the above changes, or looking for something a bit different? If you are experienced with HTML and CSS, our developer docs provide details on the Neto by Maropost specific parts of web development. If you are not comfortable editing code, we recommend submitting a request to a Neto by Maropost design partner.