Jonnie Grieve Digital Media: Blog

Home
by on 23rd August, 2024 - 12:52pm (0)

Blog: Retrieving Structured Data using Fetch, JSON and JavaScripp (More Posts)

For the past several weeks, I’ve been thinking about how I can best organise all the projects that I’ve worked on over many years. Files that are not on the internet but on my local server.  I’ve developed a system where projects of many kinds are either backed up on a web server, on a cloud system or locally using version control.

There’s a little network I’ve ended up with, comprising of version-controlled directories that I can click through when I need to find a local project or its online location. It also means I’m never too far away when I need to edit a file or local repository. And… if I ever lose directories or have to move systems they can be easily rebuilt.

Inevitably this has meant that I’ve organised just short of 150 work directories, and there are probably more to be found. These are web design and tech projects of differing levels of importance and completeness. I’ve been working constantly on an “at a glance” solution to help me keep track of them all.

And I think I’ve managed it. I start with a simple PHP file in xampp/htdocs.

I start by making an HTML table with 5 columns. This would allow me to list links to projects on my local servers; online servers, or both or neither where appropriate. But it gives me easy access to all the links and data that I need. Don’t worry too much about the other columns other than “Local” and “Online”.

<table>
    <thead>
        <tr>
            <th>Title</th>
            <th>Directory</th>
            <th>Local</th>
            <th>FPOTD</th>
            <th>Online</th>
        </tr>
    </thead>
    <tbody id="project-table-body">
        <!-- Rows will be inserted here -->
    </tbody>
</table>

Initially, I started out by going through all my projects and adding them to the table manually.

</thead>
<tbody id="project-table-body">
    <!-- Rows will be inserted here -->
    <tr>
        <td>JGDM Website</td>
        <td>jonniegrieve.co.uk</td>
        <td>No</td>
        <td>No</td>
        <td><a href="https://www.jonniegrieve.co.uk" target="blank" class="project---link">Online</a></td>
                           
    </tr>
    <tr>
        <td>Bootstrap Project</td>
        <td>projects/</td>
        <td><a href="http://localhost/jgdm-100daysofcode/css/bootstrap_project" target="blank" class="project---link">Local</a></td>
        <td>No</td>
        <td><a href="https://projects.jonniegrieve.co.uk/bootstrap_project" target="blank" class="project---link">Online</a></td>                            
    </tr>
    <tr>
        <td>CSS Project</td>
        <td>projects/</td>
        <td><a href="http://localhost/projects/castle-eden-css/" target="blank" class="project---link">Local</a></td>
        <td>Yes</td>
        <td><a href="https://projects.jonniegrieve.co.uk/castle-eden-css/" target="blank" class="project---link">Online</a></td>
    </tr>
</tbody>

It was an arduous but ultimately useful process. I could now see everything I’d compiled and could now start making decisions on which projects I could progress with. Whether one project should go in another directory or archived in another backup location completely.

But it would be better if I could get this programmed dynamically rather than have a long and bloated PHP file.

Now, I could again have done this manually. But these days we can use AI to speed up that workflow. If you can utilise its strengths and understand its pitfalls.

prompt.

convert this HTML table of data with data from an external JSON file.

Code

To convert your static HTML table into one that dynamically loads data from an external JSON file, you'll need to use JavaScript to fetch the JSON data and then populate the table. Here's a step-by-step guide on how to do it.

document.addEventListener("DOMContentLoaded", function() {

    const tableBody = document.getElementById("project-table-body");

    const projectCount = document.getElementById("js---project--count");

    // projectCount.textContent = project.length;

    fetch('project---data--dynamic.json')

        .then(response => response.json())

            .then(data => {

            data.forEach(project => {

                const row = document.createElement('tr');

                row.innerHTML = `

                `

                tableBody.appendChild(row);

                        projectCount.textContent = `${data.length}`;

                    });

                })

                .catch(error => console.error('Error loading the project list:', error));
 

row.innerHTML is a template literal that adds what’s stored in there has HTML content. It’s assigned to a table row element. Which means what we want to do is put 5 table cells as the content of the template literal. In other words, row.innerHTML, this constructs the HTML for each row, including the dynamic links for “Local” and “Online” columns. We get this data using the fetch() from a JSON file to fetch and populate the data by iterating the values.

row.innerHTML = `
    <td>${project.title}</td>
    <td>${project.directory}</td>
    <td>${project.local</td>
    <td>${project.fpotd}</td>
    <td>${project.online}</td>
`;

But this isn’t enough. We need to use condition statements in the template literal to check for the content of table cells in the local and online columns and display a text node or a hyperlink depending on its content.

This works for me because I’ll either be saying “No” to indicate no link or putting a link to a location in there.

row.innerHTML = `
    <td>${project.title}</td>
    <td>${project.directory}</td>
    <td>${project.local !== "No" ? `<a href="${project.local}" target="blank" class="project---link">Local</a>` : 'No'}</td>
    <td>${project.fpotd}</td>
    <td>${project.online !== "No" ? `<a href="${project.online}" target="blank" class="project---link">Online</a>` : 'No'}</td>
`;

The data.

[
   {
      "title": "JGDM Website",
      "directory": "jonniegrieve.co.uk",
      "local": "No",
      "fpotd": "No",
      "online": "https://www.jonniegrieve.co.uk",
   },
   {
      "title": "Bootstrap Project",
      "directory": "projects/",
      "local": "http://localhost/jgdm-100daysofcode/css/bootstrap_project",
      "fpotd": "No",
      "online": "https://projects.jonniegrieve.co.uk/bootstrap_project",
    },
    {
      "title": "CSS Project",
      "directory": "projects/",
      "local": "http://localhost/projects/castle-eden-css/",
      "fpotd": "Yes",
      "online": "https://projects.jonniegrieve.co.uk/castle-eden-css/"
    }
]

Now, based on the above code, we should be seeing 3 rows of data in the table and can now start working on converting the existing HTML data into JSON format.

I won’t bore you with that part.

But I did want to add 2 more columns to the data table.  These new columns are there to indicate whether the row is a Portfolio item and to indicate it’s status of readiness for the public.

<table>

    <thead>

        <tr>

            <th>Title</th>
            <th>Directory</th>
            <th>Local</th>
            <th>FPOTD</th>
            <th>Online</th>
            <th>Portfolio</th>
            <th>Ready</th>

        </tr>

    </thead>

    <tbody id="project-table-body">

        <!-- Rows will be inserted here -->

    </tbody>

</table>

This will need 2 more key-value pairs in the JSON data file.

[
    {
        "title": "JGDM Website",
        "directory": "jonniegrieve.co.uk",
        "local": "No",
        "fpotd": "No",
        "online": "https://www.jonniegrieve.co.uk",
        "portfolio": "No",
        "ready": "complete"
    }

]

I’ll just update the table rows to get new data from this updated file.

row.innerHTML = `
    <!-- -->
    <td>${project.portfolio}</td>
    <td>${project.ready}</td>
`;

I based my attempts to solve this on this.

<td>${project.local !== "No" ? `<a href="${project.local}" target="blank" class="project---link">Local</a>` : 'No'}</td>

But no, it’s way too convoluted to work and probably can’t be done inside a template literal. I need the help of AI again to guide me to the solution.

prompt

I need your help again. :)

Here's my html

<!-- HTML snipped -->

And a sample of my JSON file.

/* JSON Snippped */

I need to be able to modify the line <td>${project.ready}</td> in row.innerHTML so that it prints the correct values out of the following

complete
incomplete
indev
ongoing.

 

So we know that we use the “moustache” syntax to iterate through the data. And the truth is we don’t need all this convoluted condition syntax to get this to work.

row.innerHTML = `
<td>${project.title}</td>
<td>${project.directory}</td>
<td>${project.local !== "No" ? `<a href="${project.local}" target="blank" class="project---link">Local</a>` : 'No'}</td>
<td>${project.fpotd}</td>
<td>${project.online !== "No" ? `<a href="${project.online}" target="blank" class="project---link">Online</a>` : 'No'}</td>
<td>${project.portfolio}</td>
<td class="status-${project.ready.toLowerCase()}">${project.ready}</td>
`;

In my data file, the 5th “ready” column is designed to show one of 4 values.

  • complete
  • incomplete
  • indev
  • ongoing
  • review.

So if we add a class of Status to call the table cells in that column, we can match the value of the table cell with these unique classes. See what I mean?  Probably not.

But what the AI is basically saying is we are using iteration to attach unique style values to the status- class. And using these loner styles to visually differentiate the values.

<td class="status-${project.ready.toLowerCase()}"></td>

And iterating again so that the text content matches inside the table cells.

<td class="status-${project.ready.toLowerCase()}">${project.ready}</td>

 

And that is almost it for this blog.  This blog has talked about the merits of organising and backing up your work using a variety of sources and using them, where you can with a local hosting server. It has also worked through an AI-generated solution for iterating through a structured set of data.

 

This post has been assigned to the following categories

    Leave a Reply

    Your email address will not be published. Required fields are marked *