0

I'm using newsapi to request JSON data, and am then dynamically loading it onto the page without reloading the page/going onto another page.

When the user initially goes onto the site, a request made on the backend will automatically be made and load the results onto the site via an EJS template. There will also be a button at the bottom of the page, so when a user clicks on it, new articles will be loaded.

The issue is that when the user clicks on the button, the new articles aren't appended after the last instance of a card-container. For example, say I have articles 1 2 3 4 5 already on the page and want to load articles 6 7 8 9, after clicking the button the articles are now in the order of 1 6 2 7 3 8 4 9 5. Where I want it to be in the order 1 2 3 4 5 6 7 8 9.

I've thought by using Jquerys insertAfter() function to insert each new element after the last would work, but it clearly doesn't.

Whilst the code I have below may be messy, I want to fix the logic before tidying it up.

JS

let more = document.getElementById("test");

more.addEventListener("click", function () {
    (async () => {
        const data = await fetch('http://localhost:3000/articles/');

        const articles = await data.json()

        for (let i = 0; i < articles.articles.length; i++) {

            let newDate = articles.articles[i].date;
            newDate = newDate.substring(0, newDate.indexOf('T')).split("-");

            var articleList = document.getElementsByClassName("card-container");
            var lastArticle = articleList[articleList.length - 1];

            let cardContainer = document.createElement('div');
            cardContainer.className += "card-container";
            let card = document.createElement('div');
            card.className += "card";
            let content = document.createElement('div');
            content.className += "content";
            let thumbnail = document.createElement('div');
            thumbnail.className += "thumbnail";
            let image = document.createElement('img');
            image.className += "image";
            let text = document.createElement('div');
            text.className += "text";
            let title = document.createElement('div');
            title.className += "title";
            let a = document.createElement('a');
            let meta = document.createElement('div');
            meta.className += "meta";
            let source = document.createElement('div');
            source.className += "source";
            let date = document.createElement('div');
            date.className += "date";

            document.getElementsByClassName('card-container')[i]
                .appendChild(card).appendChild(content).appendChild(thumbnail)
                .appendChild(image)
            document.getElementsByClassName("content")[i]
                .appendChild(text).appendChild(title).appendChild(a)
            document.getElementsByClassName("text")[i]
                .appendChild(meta).appendChild(source)
            document.getElementsByClassName("meta")[i]
                .appendChild(date)

            let container = document.getElementById('article-container')
            container.innerHTML = container.innerHTML + cardContainer;

            image.setAttribute("src", articles.articles[i].image)
            a.setAttribute('href', articles.articles[i].link);
            a.innerHTML = articles.articles[i].title;
            source.innerHTML = articles.articles[i].source.name;
            date.innerHTML = newDate[1] + " " + newDate[2] + " " + newDate[0];

        }
    })();
})

Desired markup

<div class="card-container">
    <div class="card">
        <!-- Post-->
        <div class="content">
            <!-- Thumbnail-->
            <div class="thumbnail">
                <img
                    src="https://ssio.azurewebsites.net/x500,q75,jpeg/http://supersport-img.azureedge.net/2019/8/Man-City-190804-Celebrating-G-1050.jpg" />
            </div>
            <!-- Post Content-->
            <div class="text">
                <div class="title"><a
                        href="https://www.goal.com/en-gb/lists/deadline-day-dybala-coutinho-premier-league-transfers-happen/68rpu0erk0e81pm2anfv2ku16">Coutinho
                        llega a un acuerdo con el Arsenal para marcharse del Barcelona - PASIÓN
                        FUTBOL</a>
                </div>
                <div class="meta">
                    <div>Source</div>
                    <div class="date-text">07 07 2019</div>
                </div>
            </div>
        </div>
    </div>
</div>

JS Fiddle

I seem to have got it working - but not all of the JSON (other than the image) are being mapped to their divs inner HTML :/

https://jsfiddle.net/georgegilliland/ofxtsz2a/5/

JimmyNeedles
  • 161
  • 1
  • 8
  • 1
    I think this is a duplicate of https://stackoverflow.com/q/42517697/4342169 – Pomme De Terre Aug 09 '19 at 18:15
  • @PommeDeTerre Nope, I've tried adding the code `let articleContainer = document.getElementById('article-container') articleContainer.innerHTML = articleContainer.innerHTML + cardContainer;` after `.appendChild(date)`. Doesn't work – JimmyNeedles Aug 09 '19 at 18:28

2 Answers2

0

In order to append in pure JS you have to take the last content of the container, append new data to it, then replace the container content with the new data.

I wrote a jsfiddle based on the stack overflow question I posted in the comment : https://jsfiddle.net/HolyNoodle/bnqs83hr/1/

  var container = document.getElementById('container')

  for(var i = 0; i < 3; i++) {
    container.innerHTML = container.innerHTML + "<p>" + i + "</p>"
  }

Here you can see I am getting the container inner html, appending new value to it, then replacing the container inner html by the new html

Pomme De Terre
  • 342
  • 4
  • 14
  • Hey man, that's what I said in the comments - `let articleContainer = document.getElementById('article-container') articleContainer.innerHTML = articleContainer.innerHTML + cardContainer;` article-container is the container for all articiles - I wanted it to be appended to the end. Your solution is still giving me the same problems – JimmyNeedles Aug 09 '19 at 19:00
  • @JimmyNeedles do not use insert after. Only use this solution. With all the keys you gave me, this answer works. Please provide a jsfiddle with your problem so I can help you fix it :) – Pomme De Terre Aug 09 '19 at 19:05
  • Not sure I can provide a jsfiddle seeing as I'm making api calls? But I wasn't using insertAfter when I tried XD – JimmyNeedles Aug 09 '19 at 19:11
  • I've updated the snippet to show you what I was trying just then – JimmyNeedles Aug 09 '19 at 19:13
  • Does it still mess with the order. You can just mock the API call (as I did when I click on the button in the jsfiddle, adding element). Try reproducing the problem in the jsfiddle. – Pomme De Terre Aug 09 '19 at 19:28
  • JS Fiddle added - I may have got it working, but the content of some divs aren't being mapped to it's innerHTML... Damn – JimmyNeedles Aug 09 '19 at 23:31
  • And the order is still messed up :/ – JimmyNeedles Aug 09 '19 at 23:39
0

Fixed the issue... The problem was that I was getting elements by class name at whatever index the for loop was on. So if the for loop was on it's 5th iteration, it was appending content to the 5th instance of content, rather than appending it to the end of the container.

document.getElementById('article-container')
    .appendChild(cardContainer)
    .appendChild(card).appendChild(content).appendChild(thumbnail)
    .appendChild(image)
document.getElementsByClassName("content")[i]
    .appendChild(text).appendChild(title).appendChild(a)
document.getElementsByClassName("text")[i]
    .appendChild(meta).appendChild(source)
document.getElementsByClassName("meta")[i]
    .appendChild(date)

What I did to fix this was get the number of elements with the classname card-container before the for loop:

 let nodelist = document.getElementsByClassName("card-container").length;

And then get elements at the index of the for loop summed with the amount nodelist.

document.getElementById('article-container')
    .appendChild(cardContainer)
    .appendChild(card).appendChild(content).appendChild(thumbnail)
    .appendChild(image)
document.getElementsByClassName("content")[i + nodelist]
    .appendChild(text).appendChild(title).appendChild(a)
document.getElementsByClassName("text")[i + nodelist]
    .appendChild(meta).appendChild(source)
document.getElementsByClassName("meta")[i + nodelist]
    .appendChild(date)
JimmyNeedles
  • 161
  • 1
  • 8