1

I've problem with forEach ES6. I wrote function which add element 'div' used pure javascript. I wanted remake code to ecmascript 6 and now code didn't work. Why? I think that code is write correct wrote in ecmascript 6.

Thanks for the help

This code works:

Javascript

function addElement() {
let linkToGallery = document.getElementsByClassName("gallery-1");
for (var i = 0; i < linkToGallery.length; i++) {
    linkToGallery[i].addEventListener('click', () => {
        const newDiv = document.createElement("div");
        const newDiv2 = document.createElement("div");
        newDiv.id = "buttonGallery";
        newDiv2.innerHTML = "";
        newDiv2.innerHTML += "<div id='test'>Test</div>";
        document.body.appendChild(newDiv);
        document.body.appendChild(newDiv2);
    });
}

}

and this code didn't works why if is the same?

Ecmascript 6

function addElement() {
let linkToGallery = document.getElementsByClassName("gallery-1");
linkToGallery.forEach((current) => {
    current.addEventListener('click', () => {
        const newDiv = document.createElement("div");
        const newDiv2 = document.createElement("div");
        newDiv.id = "buttonGallery";
        newDiv2.innerHTML = "";
        newDiv2.innerHTML += "<div id='test'>Test</div>";
        document.body.appendChild(newDiv);
        document.body.appendChild(newDiv2);
    });
});

}

Thanks for the help.

  • what errors if any in the developer tools console - note: `document.getElementsByClassName("gallery-1")` is **not** an Array, therefore probably doesn't have a `forEach` method ... try `let linkToGallery = Array.from(document.getElementsByClassName("gallery-1"));` – Jaromanda X Dec 22 '17 at 06:34
  • Details and several ES6 options here: [For loop for HTMLCollection elements](https://stackoverflow.com/questions/22754315/for-loop-for-htmlcollection-elements/22754453#22754453) – jfriend00 Dec 22 '17 at 06:36
  • 1
    note: "pure javascript" code is using arrow functions and const and let ... vs "ES6 javascript" ... which is using arrow functions and const and let ... the only difference is your use of Array#forEach ... which has nothing to do with ES6. Both code snippets will only work in ES6 due to const, let and arrow function – Jaromanda X Dec 22 '17 at 06:37
  • and since the click-handler doesn't reference *(or even need)* the `current` item at all, move that function out of the loop. – Thomas Dec 22 '17 at 06:57

3 Answers3

3

I always convert array-like objects to a real array, especially since it's a lot less code involved than it used to be:

 var realArray = Array.from(document.querySelectorAll('.ele'));

or

 var realArray = [...document.getElementsByClassName("ele")];

Demo

function addElement() {
  let linkToGallery = Array.from(document.getElementsByClassName("gallery-1"));
  linkToGallery.forEach((current) => {
    current.addEventListener('click', (e) => {
      var tgt = e.target;
      tgt.textContent = 'clicked';
      const newDiv = document.createElement("div");
      const newDiv2 = document.createElement("div");
      newDiv.id = "buttonGallery";
      newDiv2.innerHTML = "";
      newDiv2.innerHTML += "<div id='test'>Test</div>";
      document.body.appendChild(newDiv);
      document.body.appendChild(newDiv2);
    });
  });
}

addElement()
section {
  border: 3px dashed red
}

div {
  border: 1px dotted blue
}
<section class='gallery-1'>Gallery 1</section>
<section class='gallery-1'>Gallery 1</section>
<section class='gallery-1'>Gallery 1</section>
<section class='gallery-1'>Gallery 1</section>
<section class='gallery-1'>Gallery 1</section>
zer00ne
  • 41,936
  • 6
  • 41
  • 68
  • How to check which element was clicked ?? – Bartłomiej Kuźniar Dec 22 '17 at 14:43
  • @BartłomiejKuźniar pass the event object into event listener then reference the `e.target` property. See update. Click any `.Gallery-1` and the text will change to: `clicked`. This proves that `e.target` is always the clicked element. – zer00ne Dec 22 '17 at 14:48
3

You can iterate array-like with for/of:

var ref = document.getElementsByClassName('gallery-1')

for (var item of ref) {
    console.log(item);
}

As I see, TypedArray%.prototype[Symbol.iterator] is supported by pretty much everyone:

Symbol.iterator

1

Another alternative to building a true Array would be to use document.querySelectorAll() to create a non-live NodeList which does have a forEach() method, unlike the live HTMLCollection returned by document.getElementsByClassName().

let linkToGallery = document.querySelectorAll('.gallery-1');

linkToGallery.forEach((current) => {
  current.addEventListener('click', () => {
    const newDiv = document.createElement('div');
    const newDiv2 = document.createElement('div');
    newDiv.className = 'buttonGallery';
    // or newDiv.setAttribute('class', ...)
    newDiv2.innerHTML = '<div class="test">Test</div>';
    document.body.appendChild(newDiv);
    document.body.appendChild(newDiv2);
  });
});
section {
  border: 3px dashed red
}

div {
  border: 1px dotted blue
}
<section class='gallery-1'>Gallery 1</section>
<section class='gallery-1'>Gallery 1</section>
<section class='gallery-1'>Gallery 1</section>
<section class='gallery-1'>Gallery 1</section>
<section class='gallery-1'>Gallery 1</section>

As a side note, you should use the class attribute instead of the id attribute, since they weren't unique within the document.

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153