Using AlpineJS Template to load data from fetch

This is a follow-up to this post of mine where I show how to retrieve data from a public google spreadsheet via their JSON output and show it in the webpage by setting the HTML to a DOM element via innerHTML. I think doing something like document.getElementById("razorui-faq").innerHTML = details; is going to be considered bad practice shortly. Just like using document.write() is frowned upon.

With Reactive libraries and frameworks like React, Angular, Vue, Svelte etc being the standard for using templates in DOM replacement methodologies, it may not be suitable to use a whole npm install for smaller, micro-websites that are used for marketing purposes or using in an existing WordPress page.

There's a faster solution - AlpineJS - it's reactive and has a smaller footprint and can be included in your webpage like you insert a jQuery CDN. Right now, all you got to do is to include https://unpkg.com/alpinejs@3.10.5/dist/cdn.min.js

<script src="https://unpkg.com/alpinejs@3.10.5/dist/cdn.min.js" defer></script>

This - we use x-init to fetch the data using await. Even the AlpineJS docs show it as x-init="posts = await (await fetch('/posts')).json()" as an example.

<div x-data="{ faqs: [] }" x-init="faqs = await fetchFAQ().then((data) => data )">
    <template x-for="faq in faqs">
        <details>
            <summary x-text="faq[0]"></summary>
            <p x-text="faq[1]"></p>
        </details>

    </template>
</div>

Get the content from the JSON as usual :

function getFAQ(json)
{    
    let faqList = [];
    let detail, summary;

    json.table.rows.forEach((row, i) =>
    {
        if (i == 0) return; // The first row is the header        

        try { detail = row.c[0].f ? row.c[0].f : row.c[0].v }
        catch(e){ detail = '' }

        try { summary = row.c[1].f ? row.c[1].f : row.c[1].v }
        catch(e){ summary = '' }

        faqList.push([detail, summary]);
    });

    return faqList;
}

The most important part: Using Promise by returning an await new Promise.

let fetchFAQ = async () =>
{
    return await new Promise((resolve, reject) =>
    {
        fetch(url)
        .then((response) => response.text())
        .then((data) =>
        {
            let json_string = data.substring(47).slice(0, -2);
            let details = getFAQ(JSON.parse(json_string));
            resolve(details);
        });
    });
}

Demo : https://anjanesh.s3.amazonaws.com/demo/fetch-alpine.html