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

concealing the date selection feature on the data picker

$('.year').datepicker({ changeMonth: true, changeYear: true, showButtonPanel: true, dateFormat: 'MM yy', onOpen: function(dateText, inst) { $("table.ui-datepicker-calendar").addClass('hide') }, onClos ...

The ng-model binding does not automatically update another ng-model within the same object

Check out this code snippet: http://plnkr.co/edit/aycnNVoD96UMbsC7rFmg?p=preview <div data-ng-app="" data-ng-init="names=['One']"> <input type="text" ng-model="names[0]"> <p>Using ng-repeat to loop:</p> <ul> ...

Generate a hyperlink that directs to a page and triggers the expansion of an accordion section

I am currently working with a Bootstrap 5 accordion component: <div class="accordion" id="accordionIndexPage"> <div class="accordion-item"> <h2 class="accordion-header" id="flush-headingOne& ...

Retrieving the value of a <select> element using React.useState in a Nextjs environment

Encountering an issue in Nextjs involving the useState function from React. There is a select element with multiple options. Upon selection, the useState should store the value of the selected option. const [value, setValue] = useState('') ... ...

Setting a default value in an arrow function

Currently, I am working on a section of code that renders a simple loading bar. const smallSpinner = document.getElementById('spinner-small').getContext('2d'); let pointToFill = 4.72; let cw = smallSpinner.canvas.width; //Returns canva ...

Click on an element that is nested within another element that can also be clicked on

I'm facing a challenge while attempting to create an accordion inside another accordion. The issue arises with the nested elements and their behavior upon clicking. Essentially, I have a parent div with the class .applicant, which expands on click by ...

API requests seem to be failing on the server side, yet they are functioning properly when made through the browser

My current project involves utilizing an API that provides detailed information about countries. I've set up an express server to handle requests to this API, but for some reason it's not making the request. Interestingly, when I directly access ...

Having trouble retrieving data in Angular from the TypeScript file

demo.component.ts import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-demo', templateUrl: './demo.component.html', styleUrls: ['./demo.component.css'] }) ...

Unusual Behavior: Node-forge AES Decryption Does Not Return the Expected Data. Issue in Angular/Typescript

Attempting to decipher a code to unveil the original information but encountering unexpected challenges. Seeking assistance: Code: general() { const foo = { pass: "Werwerw", username: "qqwewdxas" }; var key = &q ...

Is there a way to have incoming messages automatically align to the left or right based on the sender, without using the float property?

I am currently working on a webpage where I want the messages sent by different users to appear in a yellow conversation window based on who sent them - user 1 or user 2. I want it to mimic the messaging layout commonly seen on phones, distinguishing betwe ...

Using regex in Javascript to find and match an ID within a string

JavaScript: var data='<div id="hai">this is div</div>'; I am looking to retrieve only the ID "hai" using a regular expression in JavaScript. The expected output should be, var id = regularexpression(data); The variable id should n ...

Stop jQuery ajax from running any JavaScript code contained in a script or HTML response

As stated in the documentation: If html is specified, any embedded JavaScript within the retrieved data will be executed before returning the HTML as a string. Similarly, using script will execute the pulled back JavaScript before returning nothing. Is ...

What is the best way to right-align a label in a vertical MUI Slider in ReactJS?

I am currently working with ReactJS/TS and MUI (Material-UI) to develop a vertical slider that requires the label to be positioned on the right side. By default, MUI places the label on the left for vertical sliders. I have reviewed the API documentation e ...

Retrieving JSON data from a URL with PHP

Attempting to retrieve JSON data from the following URL: $search_data&format=json&nojsoncallback=1 The information I am aiming to obtain based on the above link is as follows: { "places": { "place": [ { ...

"I encountered an error stating that res.json is not a function while trying to establish a connection between ReactJS

dataset.list.js import React, { Component } from "react"; import Datasets from "./data"; import axios from "axios"; class App extends Component { render() { return <Datasets datasets={this.state.datasets} />; } ...

Refreshing CSS-Element-Queries following an ajax request

I’ve been utilizing css-element-queries from the https://github.com/marcj/css-element-queries repository to tailor styles based on an element's dimensions. However, I encountered an issue when dynamically adding elements via ajax calls. The new elem ...

Can a dynamic field name be incorporated into a JavaScript Object?

My goal is to dynamically add a field name and update the value based on that. In my situation, the eventType can have 4 types: delivery, send, open, click. However, when I implement this code, I am only getting the eventType as a string. const event = J ...

Encountering an issue with the SSR module evaluation despite having SSR disabled in Svelte Kit

I needed a specific route in my app to not be server-side rendered. This can be achieved by setting export const ssr = false in the module script or configuring ssr: false in the svelte.config.js, as outlined in the Svelte documentation. Despite disabling ...

Utilizing Javascript or XUL windows without the use of iframes offer

I'm in the process of creating a multitab website for my bookmarks, but I've run into some issues. Here is the JavaScript version of what I'm trying to achieve: Unfortunately, there are obstacles with this method. The websites in the tabs ...

Storing div content in database directly

I have a straightforward div that allows users to edit content on the page. I need to save this content in a database, but without including any HTML tags while still preserving line breaks. Currently, I am using the innerText property for this purpose. N ...