Basic DOM Manipulation
Tags: javascript, programming, html, dom
Published: 2020-11-22 00:09:13

I spent this week practicing building a basic landing page with good ole HTML, CSS, and JavaScript. No frameworks, no libraries, no nothing. I also wanted to practice fetching data from an API and displaying it on my page, and that's where my old friend DOM manipulation came in handy. I used https://jsonplaceholder.typicode.com/posts to fetch some fake posts, instead of building an API from scratch. 

Once I had finished the layout and styling, I got to work on coding the JavaScript that I would need to fetch and display the data on my page. I wanted to display four of the posts with their heading and copy, which we get from JSONplaceholder. I had already coded the necessary HTML divs with their respective IDs that I would need to target. In my main.js file I coded the variables and set them equal to the ID using document.querySelector() like this:
```
const $heading1 = document.querySelector('#post-1');
const $blog1 = document.querySelector('#post-text-1');

const $heading2 = document.querySelector('#post-2');
const $blog2 = document.querySelector('#post-text-2');

const $heading3 = document.querySelector('#post-3');
const $blog3 = document.querySelector('#post-text-3');

const $heading4 = document.querySelector('#post-4');
const $blog4 = document.querySelector('#post-text-4');
```
I then declared a variable and set it equal to the URL of the api that I would be fetching the data from. This isn't necessary, but I think it makes for cleaner and easier to read code. I also declared a variable called posts that I would utilize to store all the posts that I got back from my fetch request. Also, because you get back an array of 100 objects from the fetch request, I declared an index variable and set it equal to 4, since I would initially be displaying the first four posts. 
```
const apiURL = 'https://jsonplaceholder.typicode.com/posts/';

let posts = [];

let index = 4;

fetch(apiURL)
    .then((response) => response.json())
    .then(apiPosts => {
        posts = apiPosts;
    })
```
At this point I would also need to chain on another .then to display the posts, but I first need to write a function to populate the posts for me. This function will need to take in three arguments: a post, a heading and a blog. The body of the function will need to clear out the initial posts (this is necessary for when I create a button with an event listener to display four more posts), create the necessary elements, create the necessary classes, set the inner HTML of said elements to the appropriate title and heading, and lastly append the newly created elements to the DOM. My final function, which creates new h1 and p tags looked like this:
```
const populatePost = (post, $heading, $blog) => {
    $heading.innerHTML = "";
    let $h1 = document.createElement('h1');
    $h1.className = 'post-title';
    $h1.innerHTML = post.title;
    $heading.appendChild($h1);
    $blog.innerHTML = "";
    let $p = document.createElement('p');
    $p.className = 'post-body';
    $p.innerHTML = post.body;
    $blog.appendChild($p);
};
```
Going back to my initial fetch request, we can now call the populatePost() function and pass in the necessary arguments:
```
fetch(apiURL)
    .then((response) => response.json())
    .then(apiPosts => {
        posts = apiPosts;
    })
    .then(() => {
        populatePost(posts[0], $heading1, $blog1);
        populatePost(posts[1], $heading2, $blog2);
        populatePost(posts[2], $heading3, $blog3);
        populatePost(posts[3], $heading4, $blog4);
    })
```
Since we need four posts, we call the function four times passing in a post index, a heading variable, and a blog variable which we have already created. After checking my page, I can confirm that the necessary data was appearing.

Lastly, I wanted to create a button that when clicked, would display the next four posts. After creating and styling the button with HTML and CSS, all I had left to do was create an event listener with JavaScript. 
```
document
    .querySelector('#see-more-button')
    .addEventListener('click', () => {
        populatePost(posts[index], $heading1, $blog1);
        populatePost(posts[index + 1], $heading2, $blog2);
        populatePost(posts[index + 2], $heading3, $blog3);
        populatePost(posts[index + 3], $heading4, $blog4);
        index += 4;
        if(index > 95) {
            index = 0;
        };
    });
```
I targeted my button ID with document.querySelector(), and chained on an event listener. Event listeners take in a type and a callback function. The type I needed was click, and I used an anonymous function as my callback. I again utilized my populatePost() function. I passed in my index variable, which if we recall is set to four in the global scope which is why I add 1, 2, and 3, so I get the next four posts of 5, 6, 7, and 8. I again pass in a heading variable and a blog variable. Lastly I increment the index variable by four, so I get the next four posts on the next click. I also give a condition that if the index variable is greater than 95, the index variable gets sets to zero and we start with the first four posts again. 

I hope this post helps you to better understand DOM manipulation, and fetching data from an API a little better. 

Happy Coding!