Ways to efficiently populate HTML elements with JSON data

I am working on grasping the concept of functional programming. My understanding so far is that it involves encapsulating everything into functions and passing them around. For instance, in my current example, I am attempting to fetch data from a RESTApi and display it in the DOM:

const storyElement = function (): HTMLElement {
    const div = document.createElement('div');
    div.className = 'stories';
    return div;
};

const spinnerElement = function (): HTMLElement {
    const div = document.createElement('div');
    div.className = 'spinner';
    div.innerHTML = `<svg class="spinner" viewBox="0 0 100 100" width="20" height="20">
                        <circle cx="50" cy="50" r="42" transform="rotate(-90,50,50)" />
                    </svg>`;
    return div;
};

In this scenario, there are two divs - one for displaying Stories and another for a loading icon. Once the content is rendered, the loading icon should disappear.

function getAllStories(callback): void {
    makeRequest(baseUrl(), (res) => spawn(res, callback));
}

function spawn(content, callback): void {
    content = JSON.parse(content);

    if (content instanceof Array === false) {
        content = [content];
    }

    content.forEach(elm =>
        storyElement().innerHTML += `<h1>${elm.title}</h1>
                                     <div class="story-info">
                                        <i>ID: Post-${elm.id}</i>
                                     </div>
                                     <p>${elm.body}.</p>`
    );
    console.log(content);
    callback();
}

function displayFinished(): void {
    spinnerElement().style.display = 'none';
    document.body.innerHTML += '<div>All done!</div>';
}

However, upon executing getAllStories, the result is logged in the console but the content does not appear in the DOM:

document.body.appendChild(storyElement());
document.body.appendChild(spinnerElement());

getAllStories(displayFinished);

Any insights on why this might be happening?

Answer №1

Each instance of storyElement() being invoked within your .forEach loop generates a new element. The original element that you initially added to the DOM remains unchanged.

Answer №2

Big shoutout to @dnt for helping me tackle my problem! The fix involves creating an element and executing this sequence: fetching data from RESTAPI => injecting it into the DOM => finalizing by showing a loading icon.

function createElem(className: string, innerHTML?: string): Node {
    const div = document.createElement('div');
    div.className = className;
    if (innerHTML) {
        div.innerHTML = innerHTML;
    }
    document.body.appendChild(div);
    return div;
}

function fetchAllStories(callback): void {
    makeRequest(baseUrl(), callback);
}

function inject(content, html, callback): void {
    content = JSON.parse(content);

    if (content instanceof Array === false) {
        content = [content];
    }

    content.forEach(elm =>
        html.innerHTML += `<h1>${elm.title}</h1>
                                     <div class="story-info">
                                        <i>ID: Post-${elm.id}</i>
                                     </div>
                                     <p>${elm.body}.</p>`
    );

    callback();
}

function showCompletion(html): void {
    html.style.display = 'none';
    document.body.innerHTML += '<div>All done!</div>';
}

const storiesElem = createElem('stories');
const loadingSpinner = createElem('spinner', `<svg class="spinner" viewBox="0 0 100 100" width="20" height="20">
                        <circle cx="50" cy="50" r="42" transform="rotate(-90,50,50)" />
                    </svg>`);

fetchAllStories(res =>
    inject(res, storiesElem, () =>
        showCompletion(loadingSpinner)));

I'm now contemplating if there's a more efficient solution for my approach. Something feels off about not using simple variables for DOM elements...

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Struggling to retrieve the Object from a JSON file located at a specific URL

Apologies if this comes across as naive, but my venture into javascript and json is just starting. I'm eager to access the JSON object from the twitter API after executing var myjson; $.getJSON('url of the Object', function(data) { ...

NextJS: Error - Unable to locate module 'fs'

Attempting to load Markdown files stored in the /legal directory, I am utilizing this code. Since loading these files requires server-side processing, I have implemented getStaticProps. Based on my research, this is where I should be able to utilize fs. Ho ...

Issue: Unable to locate module 'js-yaml' while executing npm start command

Unable to locate module 'js-yaml' Require stack: D:\REACT NATIVE\portfolio\node_modules\cosmiconfig\dist\loaders.js D:\REACT NATIVE\portfolio\node_modules\cosmiconfig\dist\createExplore ...

shallow rendering does not recognize this.props as a function

I'm currently facing an issue while trying to test my (legacy) component using jest/enzyme. Here is a snippet of the component: export default class MyComponent extends Component { constructor( props ) { super( props ); this.handl ...

Guidelines for accessing a specific object or index from a dropdown list filled with objects stored in an array

Here is a question for beginners. Please be kind. I have created a select field in an HTML component using Angular, populated from an array of objects. My goal is to retrieve the selection using a method. However, I am facing an issue where I cannot use ...

Exploring the process of defining and authenticating an array of objects utilizing cuid as the key and ensuring the object contains designated properties

I have a customized data set that requires validation: { "name": "Some unique name", "blocks": [ {"cj5458hyl0001zss42td3waww": { "quantity": 9, "rate": 356.77, ...

Can we use classlist for adding or removing in Angular 2?

One of the features in my project is a directive that allows drag and drop functionality for elements. While dragging an element, I am applying classes to both the dragged element and the ones it's being dragged over. This is how I currently handle it ...

Looking to retrieve selections when the inputValue changes in react-select?

I'm working with a react-select component and I would like to implement a feature where an API request is triggered as soon as the user starts typing in the react-select field. This request should fetch items related to the keyword entered by the user ...

Unable to successfully import Node, JS, or Electron library into Angular Typescript module despite numerous attempts

I'm still getting the hang of using stack overflow, so please forgive me if my question isn't formulated correctly. I've been doing a lot of research on both stack overflow and Google, but I can't seem to figure out how to import Electr ...

The Angular material datepicker is not accurately capturing the date I am trying to select

I am facing an issue with the Angular Material datepicker where it does not select the date I choose. Instead, in my AngularJS controller, I always get the sysdate even if I select another date. Can anyone help me figure out what I am doing wrong? Here is ...

An unanticipated issue has occurred: TypeError - the product information being searched for is not defined

import { useContext, useEffect, useState } from "react" import Layout from "../components/Layout" import { ProductsContext } from "../components/ProductsContext" export default function CheckoutPage(){ const {selecte ...

Modifying audio output in a React element

I am trying to incorporate background music into my React app using TypeScript. However, I am encountering an issue where changing the music in the parent component does not affect the sound playing in the child node. import React from 'react'; ...

Tips for utilizing a variable selector with jQuery's .attr() method

In a jQuery DataTable, there is a scenario where some values can be modified by clicking an edit button. When clicked, a modal popup appears with a form to enter new values for notes and status: ... "columnDefs": [ { ...

Utilize Node.js driver to export a Mongo collection into a JSON file

How can I export a MongoDB collection to a JSON format using the Node.js driver and fs.writeFile? ...

Experiencing difficulties with mocha and expect while using Node.js for error handling

I'm in the process of developing a straightforward login module for Node. I've decided to take a Test-Driven Development (TDD) approach, but since I'm new to it, any suggestions or recommended resources would be greatly appreciated. My issu ...

The parent class has not been specified

I am facing an issue with my parent class, HTTPConnection, which I intend to use as a network utility class in order to avoid redundant code. However, when attempting to utilize it, the file core.umd.js throws an error stating Uncaught ReferenceError: HTTP ...

How can tick values be displayed on a c3js line chart when all data is unselected?

I'm currently working with a c3js line chart that displays 3 different lines. However, I noticed that when I remove all data sources, the x-axis tick values disappear. Is there a way to keep the x-axis tick values visible even when there is no data pr ...

Getting permission for geoLocation service on iOS in Ionic: A step-by-step guide

I have recently developed a social media application that utilizes geoLocation services. The app is built with Ionic 4 and has a Firebase backend. While the GeoLocation services are functioning properly on Android devices, users of iOS are not being prompt ...

The specific property 'splice' cannot be found within type 'T'

As I delve into working with TypeScript, an unexpected error arises: Property 'splice' does not exist on type 'T'. type Item = { name: string, body: string, imgOne: string, imgTwo: string, }[] // Another file contains this func ...

Obtaining the NativeElement of a component in Angular 7 Jasmine unit tests

Within the HTML of my main component, there is a my-grid component present. Main.component.html: <my-grid id="myDataGrid" [config]="gridOptions" </my-grid> In main.component.specs.ts, how can I access the NativeElement of my-grid? Cu ...