Continuing our exploration of Shopify’s Section Rendering API (see previous blog here), today we are building a simple popup modal that shows product details utilizing this API. This simple example is a starting point for building some great, dynamic content utilizing this technology. Let’s get started.
Check out the full code here: https://github.com/ndrishinski/blogs/tree/master/section-render-api-modal
Prefer Video?
Enjoy in video format otherwise read on!
Create our Custom Section
In this tutorial we will be working within the Dawn theme. First we need to create our file under the sections folder, and name it custom-product-modal.liquid
. We can first add the style tags with the given code:
<style>
/* Modal Styles */
#custom-modal {
/* position: fixed; */
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.5);
}
/* Modal Content Styles */
.custom-modal-content {
background-color: #fefefe;
margin: 15% auto;
padding: 20px;
border: 1px solid #888;
width: 50%;
min-width: 450px;
max-width: 600px;
display: flex;
border-radius: 4px;
}
/* Close Button Styles */
.custom-close-modal {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.custom-close-modal:hover,
.custom-close-modal:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
.shopify-section-template--21946272514334__image_banner {
display: none;
}
/* flex stuff */
.modal-left {
flex: 1;
}
.modal-right {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.sneaky-submit {
height: 40px;
width: 110px;
}
.modal-rt {
display: flex;
flex: 1;
justify-content: center;
align-items: center;
flex-direction: column;
}
#addToCartButton {
background-color: rgba(var(--color-button), var(--alpha-button-background));
appearance: none;
border: 0;
justify-content: center;
align-items: center;
padding: 0 3rem;
font: inherit;
text-decoration: none;
color: rgb(var(--color-button-text));
border-radius: 4px;
cursor: pointer;
}
</style>
Next we can add our HTML.
<div
class="section-id"
id="modal-section"
data-section="{{ section.id }}"
style="display: none;">
<div id="custom-modal" class="custom-modal">
<!-- Modal Content -->
<div class="custom-modal-content">
<div class="modal-left">
<!-- Product Title -->
<h2>{{ product.title }}</h2>
<!-- Product Images -->
{{ product.featured_image | image_url: width: 300 | image_tag }}
</div>
<div class="modal-right">
<div class="modal-rt">
<p>{{ product.description }}</p>
<p>{{ product.price | money }}</p>
</div>
<div class="modal-rb">
<input
type="hidden"
name="id"
id="get_product_id"
value="{{ product.variants.first.id }}">
<button id="addToCartButton">Add to Cart</button>
</div>
</div>
<!-- custom-close-modal Button -->
<span class="custom-close-modal">×</span>
</div>
</div>
</div>
This HTML/Liquid shows the product’s title, featured image, description, price and add to cart button. Also of note is the image_tag
which you can read here to learn more about. Notice that the container div has a style of display: none;
, this is because we will render the section initially, but will manipulate the style via JavaScript when we actually want it to display. Next we can add our JavaScript.
<script>
window.addEventListener("load", (event) => {
async function openModal(html, shouldShow) {
const modalHTML = html;
if (shouldShow) {
const replacingHTML = await document.querySelector("#modal-section");
replacingHTML.outerHTML = html;
}
// Get references to the modal and close button
const modal = document.getElementById("custom-modal");
const closeButton =
document.getElementsByClassName("custom-close-modal")[0];
let tempy = document.querySelector("#modal-section")
tempy.style.display = 'block'
// modal.style.display = "block";
document.getElementById("custom-modal").style.position = "fixed";
// Function to close the modal
function closeModal() {
modal.style.display = "none";
modal.style.position = "static";
}
// Event listener for the close button
closeButton.addEventListener("click", closeModal);
// Event listener to close the modal when clicking outside of it
window.addEventListener("click", function (event) {
if (event.target == modal || event.target == closeButton) {
closeModal();
}
});
}
document.addEventListener("click", async function (event) {
if (event.target.matches(".modal-selector-quick-view")) {
const targetData = event.target.dataset.target;
let response = await fetch(
`/products/${targetData}?section_id=<add your section ID here>`
);
let productMarkup = await response.text();
openModal(productMarkup, true);
} else if (event.target.matches('#addToCartButton')) {
const id = document.querySelector('#get_product_id').value
let formData = {
'items': [{
'id': id,
'quantity': 1
}]
};
fetch(window.Shopify.routes.root + 'cart/add.js', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
})
.then(response => {
window.location.href = '/cart'
return response.json();
})
.catch((error) => {
console.error('Error:', error);
});
}
});
});
</script>
IMPORTANT! You need to get the Shopify Section ID and replace it in the JavaScript for this to work correctly. We’ll cover that in just a moment. But I want to point something out that perplexed me prior to creating this. The reason we have access to the product object in this section, is because in our fetch we are calling /products/${targetData}
which will make the request from the products URL, where we will interpolate targetData
with the product handle in the next step.
Add a Quick View Button to Open Modal
Next we need to add a button to open our modal, where we will also store the product handle that we reference in our API call. Open snippets/product-card
.liquid and add:
...
<div class="card__content">
<div class="card__information">
<h4 style="z-index: 99; position: relative; cursor: pointer;" data-target="{{ card_product.handle}}" class="modal-selector-quick-view">Quick View</h4> {% comment %} <--- add here {% endcomment %}
...
Now our event listener has an element to watch for.
Add Section to Theme Customizer
In order to add this section via the Theme Customizer, we need to add the following schema to the bottom of the custom-product-modal.liquid
:
{% schema %}
{
"name": "Quick View Modal",
"limit": 1,
"settings": [
{
"type": "checkbox",
"id": "title",
"label": "Text"
}
],
"presets": [
{
"name": "Quick View Modal",
"settings": {
"title": "Quick View Modal"
}
}
],
"enabled_on": {
"templates": ["*"]
}
}
{% endschema %}
After saving, we can add this to the homepage via the Theme Customizer:
Finding the Section ID
The last step here, is to find our section ID that we can replace in the JavaScript above. If we open up the inspector of our browser and search for “modal-section”, we can copy the section ID from the ‘data-section’ attribute. It should start with ‘template–‘.
And in our custom-product-modal.liquid
file, we can add it to our JavaScript like so:
`/products/${targetData}?section_id=template--22031678636318__custom_product_modal_VGDTKG`
Conclusion
Now when we save, and open our preview we should have a fully functioning popup modal utilizing the Section Rendering API on our featured collection. I hope you enjoyed this tutorial and stay tuned for more Shopify development content!