Home > Back-end >  "for...of" loop on JSON response only shows first and last result
"for...of" loop on JSON response only shows first and last result

Time:08-02

Bare with me, still a js noob.

I'm doing a Fetch GET request to my database. JSON response is working to the console, I can see an array of 5 unique items. No console errors.

But rendering to the page I only get two items to display. Item 0 repeats 4 times and item 4 displays once. Odd. Something wrong with the way I'm using the "for...of"loop I guess, but I've pulled my hair out trying stuff and dunno what I'm doing.

Appreciate anyones help here. Jobslist Dashboard Screenshot attached [1]: https://i.stack.imgur.com/Xb9Ra.jpg [![dashboard][1]][1]

let url = new URL('//HIDDEN_URL_ENDPOINT');

async function getJobs() {
    let data;

    try {
        const response = await fetch(url);
        data = await response.json();
    } catch (error) {
        console.log('error', error);
    }

    const jobContainer = document.getElementById("job_list");
    const jobRecords = data;

    for (const jobRecord of jobRecords) {

        const style = document.getElementById('sample_job')
        const job = style.cloneNode(true)
        job.setAttribute('id', 'nodeJobs');

        document.querySelector("#job_title").innerHTML = jobRecord.job_title;
        document.querySelector("#job_type").innerHTML = jobRecord.job_type;
        document.querySelector("#job_level").innerHTML = jobRecord.job_level;
        document.querySelector("#job_salary").innerHTML = jobRecord.job_salary;
        document.querySelector("#job_status").innerHTML = jobRecord.job_status;
        document.querySelector("#formated_date").innerHTML = jobRecord.formated_date;
        document.querySelector("#page_views").innerHTML = jobRecord.page_views;
        document.querySelector("#apply_clicks").innerHTML = jobRecord.apply_email_clicks;

        jobContainer.appendChild(job);
    }
}

getJobs();

CodePudding user response:

The problem is that:

  • querySelector will return the first match, so it will always find the same element in each iteration of the loop, and -- related --
  • you generate HTML that has id attributes that are not unique (which is invalid in HTML)

So:

  • Don't give the cloned elements an id attribute at all. You shouldn't need that. The original sample element could have one id, but remove it in the clone.
  • Don't use id attributes in this template's inner structure at all, but use class instead
  • Make querySelector calls that start from the element that was just added, not document

Something like this (after you have adapted the HTML of sample_job):

    for (const jobRecord of jobRecords) {

        const style = document.getElementById('sample_job')
        const job = style.cloneNode(true)
        job.removeAttribute('id');

        job.querySelector(".job_title").innerHTML = jobRecord.job_title;
        job.querySelector(".job_type").innerHTML = jobRecord.job_type;
        job.querySelector(".job_level").innerHTML = jobRecord.job_level;
        job.querySelector(".job_salary").innerHTML = jobRecord.job_salary;
        job.querySelector(".job_status").innerHTML = jobRecord.job_status;     
        job.querySelector(".formated_date").innerHTML = jobRecord.formated_date;
        job.querySelector(".page_views").innerHTML = jobRecord.page_views;
        job.querySelector(".apply_clicks").innerHTML = jobRecord.apply_email_clicks;

        jobContainer.appendChild(job);
    }        

The HTML wasn't provided, but the idea is something like this:

<div id="sample_job">
    <div ></div>
    <div ></div>
    <!-- ...etc... -->
</div>

CodePudding user response:

You just need to replace document by your job element, and preferably replace all ids by classnames for example because the id should be unique (and of course replace the # in the selector by . if you did so):

        job.querySelector("#job_title").innerHTML = jobRecord.job_title;
        job.querySelector("#job_type").innerHTML = jobRecord.job_type;
        job.querySelector("#job_level").innerHTML = jobRecord.job_level;
        job.querySelector("#job_salary").innerHTML = jobRecord.job_salary;
        job.querySelector("#job_status").innerHTML = jobRecord.job_status;
        job.querySelector("#formated_date").innerHTML = jobRecord.formated_date;
        job.querySelector("#page_views").innerHTML = jobRecord.page_views;
        job.querySelector("#apply_clicks").innerHTML = jobRecord.apply_email_clicks;
  • Related