2

I want to render Images with JavaScript into my HTML-File. I can't find the problem, here is my code from the JavaScript and the HTML. Really appreciate when someone can help me.

Than you!

const imgs = [
    "images/p1.jpg",
    "images/p2.jpg",
    "images/p3.jpg"
]

const container = document.getElementById("container")

function renderImages() {
    let getImgs = ""
    for (let i = 0; i < imgs.length; i++) {
        getImgs = `<img scr="${imgs[i]}">`
    }
    container.innerHTML = getImgs
}

renderImages()



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Headline</h1>
    <div id="container">

    </div>


    <script src="index.js"></script>
</body>
</html>
Nick_S
  • 45
  • 4
  • What your script does is not what most people would consider "rendering images" (I was thinking you'd be drawing using `Canvas`) – Dai Sep 04 '21 at 18:36
  • Have you use your browser's JS debugger to investigate the problem? **If not, why not?** – Dai Sep 04 '21 at 18:36
  • You should avoid using `innerHTML` (it's slow and insecure: it opens you up to XSS vulnerabilities). Instead use `document.createElement` and `appendChild` to add new elements to the DOM. – Dai Sep 04 '21 at 18:37
  • @Dai `innerHTML` is insecure, yes, but it is faster than `document.createElement` especially if you build the HTML string then call `innerHTML` once. – slebetman Sep 04 '21 at 18:39
  • the code you provided will only add "images/p3.jpg" to your container with 0 width and 0 height. try adding style to your image. – fatemeh fallahi arezoudar Sep 04 '21 at 18:40
  • this will not work: `` See here how to use template literals https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals – J_K Sep 04 '21 at 18:47
  • You spelled wrong src attribute in img tag its 'src' not 'scr' – Ameer Hamza Sep 04 '21 at 18:51
  • @slebetman The only benchmark I can find that shows `innerHTML` to be faster is the QuirksMode page from 2007 which only concerns building a table element ( https://www.quirksmode.org/dom/innerhtml.html ) so I’m not convinced. And even if it is faster, there any many other non-performance reasons for preferring `createElement` still: https://stackoverflow.com/questions/2946656/advantages-of-createelement-over-innerhtml – Dai Sep 04 '21 at 20:13

4 Answers4

2

The problem is that you use an equal sign (=) rather than a plus-equal sign (+=). The plus-equal sign will add the text to the variable, while the equal sign will overwrite the variable.

This line:

        getImgs = `<img scr="${imgs[i]}">`

getImgs is being set to the string, the string is not being added to it. You need to change it to something like this:

        getImgs += `<img scr="${imgs[i]}">`

(Notice the plus before the equal sign)

This way, the variable will not be completely changed, rather it will be appended to.

Full code:

const imgs = [
    "images/p1.jpg",
    "images/p2.jpg",
    "images/p3.jpg"
]

const container = document.getElementById("container")

function renderImages() {
    let getImgs = ""
    for (let i = 0; i < imgs.length; i++) {
        getImgs += `<img scr="${imgs[i]}">`
    }
    container.innerHTML = getImgs
}

renderImages()
/* I added css so you can see the images */
img {
  border: 1px solid black;
  width: 20px;
  height: 20px;
  background: linear-gradient(90deg, blue, green);
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>Headline</h1>
    <div id="container">

    </div>
</body>
</html>

The CSS was added just so you can see where the images are.

Brendan R.
  • 113
  • 1
  • 6
0
const imgs = [
    "images/p1.jpg",
    "images/p2.jpg",
    "images/p3.jpg"
]; // list of sources of images to be rendered

const container = document.getElementById("container"); // the element that is going to contain those images

const loadImage = url => {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => resolve(img); // resolve the promise if the image has been successfully loaded
    img.onerror = () => reject(); // else reject the promise
    img.src = url; // set the source only after the event handlers have been set
  });
};

const renderImages = async () => {
   try {
     const loadedImages = await Promise.all(imgs.map(loadImage));
     const frag = document.createDocumentFragment();
     frag.append(...loadedImages);
     container.appendChild(frag); 
   } catch {
     console.error("Couldn't render the images");
   }
};

renderImages();

here the loadImage function is used to load the images and it returns a promise that resolves only when the images have been loaded

then in the renderImages function we await until all the images have been loaded then we append all those images to a document fragment so to reduce the number of dom updates, then finally we append that document fragment to the container.

I hope it helps and please pardon my bad english.

  • I tried your code, and it will load the images. But I am very new into web development, so i cant fully understand your code. :D My code works now, it was only a spelling mistake and a small mistake with = and +=. Thanks a lot for your help! Your English isn't bad, just saying :) – Nick_S Sep 04 '21 at 20:44
0

With your code, the result is just one image tag(img): result with your code

You must include the innerHTML inside of the loop: InnerHTML inside the loop

And that's all. HTML result

  • It is better to put code and snippets in your answers, please, avoid using images, especially with code – Dmytro Sep 04 '21 at 19:56
  • Please provide additional details in your answer. As it's currently written, it's hard to understand your solution. – Community Sep 04 '21 at 19:56
0

All you have to do is go to your line inside your for loop:

getImgs = `<img scr="${imgs[i]}">`

And change it to

getImgs += `<img src="${imgs[i]}">`

Errors:

  • You had scr="${imgs[i]}" insead of src="${imgs[i]}". (src instead of scr)
  • Another issue was getImgs =. That should be +=, because otherwise every time you are making getImgs equal the last img. With +=, you are adding a new image element to getImgs each time, so at the end of the loop getImgs contains all of the img tags.

  • Another Route to Success

    Instead you could rewrite your function to something like this:

    function renderImages() {
        for (let i = 0; i < imgs.length; i++) {
            container.innerHTML += `<img src="${imgs[i]}">`
        }
    }
    

    Which is perhaps more compact.

    Tiernan Crotty
    • 187
    • 1
    • 10
    • Thanks a lot for your help! I just did not see the spelling mistake... Now everything works! Thank you very much! – Nick_S Sep 04 '21 at 20:41