Rolf B: Javascript: input-Element nachträglich einbinden - oninput und onblur funzen nicht

Beitrag lesen

Hallo Linuchs,

Gunnar hat Dir bestimmt schon sieben Mal gesagt, dass Placeholder kein Ersatz für Labels sind. Ich sage es Dir hiermit zum achten Mal.

Klappt soweit bis auf oninput und onblur, die sind im Code nicht zu sehen, also keine Verbindung zur DB.

Könntest Du dieses Problem vielleicht mit mehr und klareren Worten beschreiben? Für mich ist dieser Satz unverständliches Kauderwelsch. Wieso ist es für die Verbindung zur DB relevant, ob die oninput und onblur-Eigenschaften im Code zu sehen sind? Wobei ich auch nicht verstehe, warum sie nicht zu sehen sein sollten.

Jedes input-Element hat die oninput und onblur-Eigenschaft. Darin findest Du die Funktion, die der Browser Dir aus dem String generiert hat, den Du im oninput- bzw. onblur-Attribut notiert hast. Willst Du den Attributinhalt, dann verwende bspw. den Methodenaufruf inputElem.getAttribute("oninput"). Aber ich wüsste nicht, wofür das von Bedeutung wäre.

Das input-Element selbst übergibst Du ja eh als Parameter an getLieder, und das ist das eigentlich wichtige im Eventhandling. Ich hoffe, du legst um die input-Elemente einer Titelgruppe zumindest ein div. Damit fällt die Navigation zu den Nachbarinputs deutlich leichter.

Dass es sinnvoller ist, Eventhandling mit addEventListener zu betreiben, und dass ein Debouncer für die Suche sinnoll ist, kann ich nur unterschreiben. Zu beiden Themen findest Du einiges im Selfwiki.

Grundsätzlich würde ich die Eventlistener aber auch nicht auf den inputs direkt definieren, sondern auf einem gemeinsamen Elternelement und dann das Bubbling nutzen. Mal angenommen, das HTML sähe so aus (du hast doch eine Liste für die Titelliste verwendet, oder?)

<ol class="titelListe">
<li>
  <div>
    <label for="titel_1">Titel</titel>
    <input type="text" id="titel_1" name="titel_1" required ...>
  </div>
  <div>
    <label for="komponist_1">Komponist</titel>
    <input type="text" id="komponist_1" name="komponist_1" ...>
  </div>
  <div>
    <label>Bearbeiter</titel>
    <input type="text" id="bearbeiter_1" name="bearbeiter_1" ...>
  </div>
</li>
...
</ol>

Praktisch wird es anders aussehen, wegen der vergrößerten Indexnummern. Stylen kannst Du das jedenfalls alles ausgehend von .titelListe.

Die Eventhandler für input und blur definiere dann auf dem ol Element!!!

const titelListe = document.querySelector(".titelListe");
titelListe.addEventListener("input", getLieder);
titelListe.addEventListener("blur", getLiederSchliessen);

function getLieder(inputEvent) {
   const eingabe = inputEvent.target;      // Das input-Element, das das Event gefeuert hat
   const eintrag = eingabe.closest("li");  // Das li-Element dieser Eingabegruppe

   const titel = eintrag.querySelector("input[name^=titel]");
   const kompo = eintrag.querySelector("input[name^=kompo]");
   const bearb = eintrag.querySelector("input[name^=bearb]");

   // Jetzt hast Du alle 3 Felder im Zugriff
   if (eingabe == titel) {   // Es wurde etwas im Titel eingegeben
    ... suchen
    titel.value=suchErgebnis.titel;
    kompo.value=suchErgebnis.komponist;
    bearb.value=suchErgebnis.bearbeiter;
   }
}
function getLiederSchließen(blurEvent) {
}

Ich kann den richtigen Code jetzt natürlich nur andeuten, bei Dir ist das in Callbacks vom Ajax-Aufruf verpackt. Aber ich hoffe, ich konnte Dir die Idee zeigen.

Für einen neuen Eintrag baust Du Dir das innerHTML für das neue li Element als String zusammen. Und zwar in einer Funktion, damit Du prima mit einem Template-String arbeiten kannst, um die Indexnummer überall einzusetzen wo sie gebraucht wird. Welche das ist, musst Du natürlich erstmal rausfinden - aber das hast Du ja eh schon drin.

titelListe.append(createNewItem(index));


function createNewItem(index) {
   item = document.createElement("li");
   item.innerHTML = 
`<div>
    <label for="titel_${index}">Titel</titel>
    <input type="text" id="titel_${index}" name="titel_${index}" required ...>
  </div>
  <div>
    <label for="komponist_${index}">Komponist</titel>
    <input type="text" id="komponist_${index}" name="komponist_${index}" ...>
  </div>
  <div>
    <label for="bearbeiter_${index}">Bearbeiter</titel>
    <input type="text" id="bearbeiter_${index}" name="bearbeiter_${index}" ...>
  </div>`;

   return item;
}

Im Detail wird das bei Dir natürlich anders aussehen.

Rolf

--
sumpsi - posui - obstruxi