Pridávanie obslužných rutín k novým prvkom v JavaScripte

Predpokladajme, že máme zoznam ul a tlačidlo:

html<ul>
  <li>položka</li>
  <li>položka</li>
  <li>položka</li>
  <li>položka</li>
  <li>položka</li>
</ul>

<button>pridať</button>

Získajme naše prvky do príslušných premenných:

javascriptlet button = document.querySelector('button');
let list   = document.querySelector('ul');
let items  = list.querySelectorAll('li');

Nastavme to tak, aby po kliknutí na ľubovoľnú li sa jej na koniec pridala výkričník:

javascriptfor (let item of items) {
  item.addEventListener('click', function() {
    this.textContent = this.textContent + '!';
  });
}

Teraz nastavme, aby po stlačení tlačidla sa na koniec zoznamu pridala nová li:

javascriptbutton.addEventListener('click', function() {
  let item = document.createElement('li');
  item.textContent = 'položka';
  list.appendChild(item);
});

Avšak narazíme na problém: kliknutie na novú pridanú li nepovedie k pridaniu výkričníka na koniec. Dôvod je v tom, že pridávame obslužnú rutinu kliknutia len na tie li, ktoré existovali spočiatku, ale nie na nové.

Opravme problém pridaním obslužnej rutiny kliknutia na novú li:

javascriptbutton.addEventListener('click', function() {
  let item = document.createElement('li');
  item.textContent = 'položka';
  
  item.addEventListener('click', function() { // obslužná rutina kliknutia
    this.textContent = this.textContent + '!';
  });
  
  list.appendChild(item);
});

Avšak teraz sa kód obslužnej funkcie duplikuje na dvoch miestach - pre pôvodne existujúce li a pre nové. Opravme to vyňatím jeho do samostatnej funkcie:

javascriptfunction handler() {
  this.textContent = this.textContent + '!';
}

Použime našu funkciu, aby sme sa vyhli duplikovaniu kódu:

javascriptfor (let item of items) {
  item.addEventListener('click', handler);
}

button.addEventListener('click', function() {
  let item = document.createElement('li');
  item.textContent = 'položka';
  
  item.addEventListener('click', handler);
  
  list.appendChild(item);
});

Úloha je v podstate vyriešená a vyhli sme sa duplikovaniu kódu obslužnej funkcie. Avšak, pridávať obslužné rutiny udalostí nám aj tak príde na dvoch miestach: both v cykle pre existujúce li, a pri kliknutí na tlačidlo. V nasledujúcej lekcii si predstavíme spôsob, ako sa tohto nepohodlia zbaviť.