How Dawn Theme Uses Section Rendering API for Cart Refresh


If a Shopify Theme developer ever wonders how to approach an API or feature build out, the Dawn theme is the best place to start. One standout aspect is its adept utilization of the section rendering API to streamline the cart-refreshing process. With a breakdown of this mechanism, we delve into the intricate workings of how the Dawn theme updates the cart in real-time. Join me as we uncover the inner workings of the Shopify Dawn theme, showcasing its commitment to efficiency and user-centric design, and gain the skills to build out a custom rendering in our next blog!

Prefer Video?

If you’d prefer to follow along with video enjoy, otherwise read on!

Investigating cart.js

In a previous blog, we came across the web component utilization of the Dawn cart. If you haven’t explore web components, I’d recommend reading that blog first. Within cart.js there are some event listeners in place, that when an item in the slideout cart is updated or removed a couple of functions are fired off. We want to focus specifically on the updateQuantity function which is called anytime the quantity plus or minus button is clicked.

updateQuantity(line, quantity, name) {
    this.enableLoading(line);
    const body = JSON.stringify({
      line,
      quantity,
      sections: this.getSectionsToRender().map((section) => section.section), // Including the sections we wish to render
      sections_url: window.location.pathname
    });
...

While creating the body of our post request to the cart_change_url you’ll notice that we are including a key of sections, with a value referencing the getSectionsToRender(). So what is that?

Request Sections within Ajax API

If we look at the Shopify documentation here, it says: “To request sections, you can include a sections parameter in your API call data…The HTML for the requested sections is included under the sections key of the returned JSON. Each section can be identified by the same ID that was passed in the request.”

This is pretty cool because we can get a 2 for 1 while calling the Ajax API. Meaning while we are updating the cart, we can get the section HTML in the same response! So when we look at the getSectionsToRender() function back in Dawn:

getSectionsToRender() {
    return [
      {
        id: 'main-cart-items',
        section: document.getElementById('main-cart-items').dataset.id, // getting the section ID eg. template--21946272514334__nick-custom-section
        selector: '.js-contents'
      },
...

All we are really doing is returning an array with the sections we want the Ajax API to respond with.

Parse the Returned Section HTML

If we look back at our updateQuantity function we’ll see the fetch and response handling:

updateQuantity(line, quantity, name) {
...
fetch(`${routes.cart_change_url}`, { ...fetchConfig(), ...{ body } })
      .then((response) => {
        return response.text();
      })
      .then((state) => {
        const parsedState = JSON.parse(state); // response is in JSON -> BUT parsedState.sections will have our HTML
        const quantityElement = document.getElementById(`Quantity-${line}`) || document.getElementById(`Drawer-quantity-${line}`);
        const items = document.querySelectorAll('.cart-item');
...

Here we are handling the promise returned with JSON parse because the Ajax cart response is JSON, however the sections key of the response will have our Sections HTML we are after. The parsed response looks like this:

{
   "token":"c1-e7300b81b427f67d9f5ea48c3156ecca",
   "original_total_price":74995,
   "total_price":74995,
   "total_discount":0,
   "total_weight":0.0,
   "item_count":1,
...
  "sections": {
     "cart-drawer": `<div id="shopify-section-cart-drawer"...</div>` 
  }

So if we look a little further:

this.getSectionsToRender().forEach((section => {
          const elementToReplace = 
            document.getElementById(section.id).querySelector(section.selector) || document.getElementById(section.id);
          elementToReplace.innerHTML = 
            this.getSectionInnerHTML(parsedState.sections[section.section], section.selector); // Updating the DOM here
        }));

We are calling a function getSectionsToRender() which we already know has our sections we requested, and looping through each one to update in the DOM. The function getSectionInnerHTML() is responsible for parsing the passed HTML response and selector which we then update by calling elementToReplace.innerHTML =.

Conclusion

There is a lot of extra code here doing additional things like error handling and displaying messages to the user, but this has been a recap of the basic workflow of the Dawn Ajax Cart updating process using the Section Rendering API. I hope you enjoyed and stay tuned for part 2 when we create our own custom section to render via the Section Rendering API.