addEventListener nacheinander für mehrere Elemente?


05.11.2023, 12:07

Hier ist der ganze Code:

let field = 0;

let idNames = [];

let allNotices = [];

function add(){ //Fügt dem Sidebar einen Kasten hinzu

textarea = document.getElementById("textfield");

notice = document.getElementById("textfield").value;

sidebar.innerHTML += `<li><button type="button" class="sidebarNotice" id="button`+field+`">${notice}</button></li>`; //Fügt den Kasten hinzu

addOnclick();

textarea.value = ``;//Leert das Textfeld

plus(); //Erhöht field um eins

function plus(){

field++;

}

}

function addOnclick(){ //Fügt zum Array aller idNames den aktuellen ID-Namen hinzu

actual = `button` + field;

idNames.push(actual);

allNotices.push(x);

addOnclick2(); //Führt addOnclick2 für die aktuelle NOtitz aus

}

function addOnclick2(){

toShow = allNotices[field]

console.log(toShow);

document.getElementById(idNames[field]).addEventListener("click", function(){showNotice(toShow)}); //anstelle von forEach

console.log("der EventListener wurde hinzugefügt");

}

function showNotice(x){

console.log("showNotice() wurde ausgeführt")

textarea = document.getElementById("textfield");

textarea.value = x;

}

2 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Da du auf ein Event des jeweiligen Buttons reagieren möchtest, musst du diesem auch den Listener anhängen.

Dafür gibt es unterschiedliche Lösungswege. Ich stelle einmal drei vor:

a)

const button = document.createElement("button");
button.type = "button";
button.classList.add("sidebarNotice");
button.id = `button${field}`;
button.textContent = notice;
button.addEventListener("click", evt => { /* ... */ });

const listItem = document.createElement("li");
listItem.appendChild(button);
sidebar.appendChild(listItem);

b)

// after innerHTML
sidebar.querySelector(`#button${field}`).addEventListener("click", evt => { /* ... */ });

c)

sidebar.innerHTML += `<li><button onclick="doSomething(this)" type="button" class="sidebarNotice" id="button` + field + `">${notice}</button></li>`;

// doSomething:
function doSomething(sender) {
  // ...
}

Die erste Option dürfte in der Performance am schnellsten sein. Beim zweiten Weg müsste der Button erst im DOM gesucht werden, beim dritten Weg wird ein Handler via onclick angehängt.

Bezüglich deines Code würde ich ein paar Verbesserungen und Vereinfachungen vorschlagen.

1) Fasse Notizinhalt und ID zusammen. Du brauchst insgesamt nur ein Array.

const notes = [];

// add:
notes.push({ content: "Hello world!", id: "some-id" });

// find:
const note = notes.find(n => n.id === "searched id");

Alternativ könntest du die Notizen ebenso in einem Objekt speichern, wobei die ID dem Propertynamen entspricht.

const notes = {};

// add
notes["some-id"] = "Hello world!";

// find
const note = notes["searched id"];

Der Button bekommt natürlich wie zuvor auch noch die ID, um später bei Klick die entsprechende Assoziation herstellen zu können.

An der Stelle würde ich allerdings noch hinterfragen, wieso du die Notiz ebenso als Buttonbeschriftung nutzt. Zum einen werden deine Buttons (im Normalfall) so doch ziemlich gestreckt und zum anderen brauchst du dann auch kein Array/Objekt mehr, welches die Notizen separat speichert. Bei Klick kommst du genauso gut via

button.textContent

an den Notizinhalt heran.

2) Die Suche von Elementen im DOM würde ich stets versuchen zu reduzieren. Die Referenz auf das Textfeld kannst du dir global (außerhalb deiner Funktionen) speichern.

const textarea = document.getElementById("textfield");

function add() {
  const note = textarea.value;
  /* ... */
}

Hinsichtlich deiner textarea-Variable möchte ich zudem anmerken, dass du sie derzeit stets als globale Variable anlegst. Das passiert mit allen Variablen, die du ohne let/const/var deklarierst.

3) Noch zwei weitere unnötige Operationen sind dein Templatestring für das Leeren des Textfelds und die plus-Funktion. Einfacher, schneller und kürzer:

textarea.value = "";
++field;

4) Die Funktionen addOnClick und addOnClick2 braucht es nicht, zumal die zweitgenannte Funktion nicht gut benannt ist.

Innerhalb des Event Handlers kannst du problemlos auf die Attribute des angeklickten Buttons zugreifen.

Beispiel:

button.addEventListener("click", evt => {
  // by event object
  const clickedButton = evt.currentTarget;
  console.log(clickedButton.id);

  // by global event object
  const clickedButton2 = event.currentTarget;
  console.log(clickedButton2.id);

  // by button variable from outside
  console.log(button.id);
});

Bei Einsatz von onclick (s. o.) verweist der Parameter sender auf den Button.

Biskan 
Fragesteller
 06.11.2023, 19:01

Vielen Dank für deine Antwort! Ich werde meinen Code nach deinen Vorschlägen überarbeiten, bisher habe ich nur den Teil mit dem EventListener ausprobiert und leider hat es nicht funktioniert: jeder Button erhält das onclick Element, aber alle zeigen die selbe Notitz an - den aktuellen Wert von "notice", obwohl sie ja via addEventListener einen anderen Parameter zugewiesen bekommen haben. Anscheinend wird der Parameter aller Buttons auf den neuseten Wert von "notice" aktualisiert.

0
regex9  06.11.2023, 19:03
@Biskan

Falls du die Fehlerursache nicht selbst findest, lege einmal ein Fiddle mit deinem kompletten Code an, speichere es und teile dessen URL hier.

0
regex9  06.11.2023, 20:28
@Biskan

Du legst die Variable notice global an. Das heißt, immer wenn du eine Notiz anlegst, veränderst du den Wert der gleichen Variable, der bei Klick auch angezeigt wird.

Sie muss als lokale Variable in add angelegt werden.

function add() {
  textarea = document.getElementById("textfield");
  const notice = textarea.value; // local variable

  /* etc. ... */
0
Biskan 
Fragesteller
 07.11.2023, 06:56
@regex9

😱Oh mein Gott! Ich hätte nicht gedacht, dass es so einfach ist. Vielen Dank noch einmal, auch für alle anderen Verbesserungsvorschläge. Bin erst seit ein paar Tagen Mitglied und treffe schon auf so hilfsbereite Leute :-)

0

Das ist absolut unsauber programmiert. Ich erkenne überhaupt keine Logik um da einen Fehler finden zu können. Zu wissen, welche Sprache das ist, wäre auch nett. Ich tippe aber mal auf JS.

Du gibst, wenn ich es richtig verstehe, mehrere Elemente aus. Jedes Element muss eindeutig für den eventListener identifizierbar sein. Sonst geht es nicht. Vermutlich ist es einfacher, wenn du ein onClick-Event direkt in den Code des Elements mit einbaust per Funktion, weil du dann nicht mit den Listenern herumpfuschen musst. Am Ende iterierst du irgendwo falsch und bums geht eine falsche Notiz auf.

Biskan 
Fragesteller
 05.11.2023, 12:00

Es kann gut, sein, dass dies alles ziemlich umständlich ist, ich bin totaler Anfänger. Ich benutzte kein onclick, da ich die einzelnen Buttons per innerHTML erstelle und ich es dort nicht geschafft habe, Parameter in einer Funktion zu übergeben.

Und entschuldige, du hast recht, ich habe das in JS gecodet.

0
verreisterNutzer  05.11.2023, 12:02
@Biskan

Dann solltest du vielleicht erstmal kleinere Projekte versuchen :)

Nachdem ich keinen ganzen Code habe, ist es eh schwer zu helfen. Eigentlich ist das nicht wirklich umständlich, wenn man es richtig anstellt...

0