Zugriff auf dynamische Felder

  • Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

ZK_Crunchy

Mitglied
21 Januar 2021
45
0
6
24
Hallo zusammen!

Ich habe ein Formular entwickelt, welches dynamisch erweiterbar ist. Dazu möchte ich alle erstellen Felder (bereits vorhanden und dynamisch erzeugte) am Ende summiert abbilden. Nun habe ich aber die Problematik, dass ich die Felder per ID nicht summieren kann, da nicht alle IDs immer vergeben sind.

Ein Beispiel um es zu verdeutlich:

Beim Öffnen des Formulars sind die IDs 1-10 vorhanden. Beim ersten Erweitern kommen die IDs 11-15 dazu. Usw. Ich möchte bis zu maximal 30 IDs aufsummieren. Jedoch kann ich diese nicht von Anfang an abfragen, da ich sonst Error Codes produziere. Klar, ich möchte auf nicht vergebene IDs zugreifen. Das geht nun mal nicht. Habt ihr eine Idee, wie ich das lösen kann?

Vielen Dank im voraus!
 
Werbung:

basti1012

Senior HTML'ler
26 November 2017
1.532
167
63
Minden
sebastian1012.bplaced.net
Ein Beispiel um es zu verdeutlich:
Es wäre gut, wenn du da deinen letzten Code posten könntest.
Du kannst auch bei codepen.io einen funktionierendes Beispiel erstellen, was du bis jetzt hast.

In den fall, wäre ein Code ganz gut.
Ich verstehe das so,
Du hast 10 Felder mit 10 verschiedene ID's.
Möchtest noch weitere Felder erstellen, z. B. noch 10.
Feld 1-10 kannst du von Anfang an ohne Probleme Abfragen.
Feld 10-20 sind am Anfang ja nicht da und eigentlich auch erst Abfragbar, wenn sie erstellt wurden.
Ich möchte dir jetzt nicht fertiges posten deswegen zeige doch mal dein Code was du schon gemacht hast
 
Werbung:

jonas3344

Mitglied
25 Oktober 2019
94
27
18
37
Du kannst mit JavaScript Elemente auf ganz verschiedene Arten selektieren. Über ID wie du das versuchst, aber auch über Klassen oder über Element-Typ, etc. Da gibts viele Möglichkeiten, ich verwende mittlerweile kaum mehr die id.
 

ZK_Crunchy

Mitglied
21 Januar 2021
45
0
6
24
Es wäre gut, wenn du da deinen letzten Code posten könntest.
Du kannst auch bei codepen.io einen funktionierendes Beispiel erstellen, was du bis jetzt hast.

In den fall, wäre ein Code ganz gut.
Ich verstehe das so,
Du hast 10 Felder mit 10 verschiedene ID's.
Möchtest noch weitere Felder erstellen, z. B. noch 10.
Feld 1-10 kannst du von Anfang an ohne Probleme Abfragen.
Feld 10-20 sind am Anfang ja nicht da und eigentlich auch erst Abfragbar, wenn sie erstellt wurden.
Ich möchte dir jetzt nicht fertiges posten deswegen zeige doch mal dein Code was du schon gemacht hast
Das hast du genau so richtig verstanden.

Mein Code ist sehr groß, aber ich versuche mal die relevanten Teile zu posten:

Das ist die Funktion zum Erweitern des HTMLs. Es wird ein Template eingefügt und die IDs werden nummeriert. Bei jedem Einfügen wird die ID um eins erhöht. Für jedes Feld.

Code:
<script>
            let nrDay = 1;
        
            function newDay(addBtn){
                
                //Nummer des Tages erhöhren
                nrDay++;
                
                //HTML aus dem Template lesen
                let html = document.getElementById('new_passage').innerHTML;
                
                //Alle Vorkommen des Platzhalters, durch Nummer des Tages ersetzen
                html = html.replace(/{\{nrtag\}\}/g, nrDay);
                
                //Template einfügen
                //document.querySelector('.Feld3').insertAdjacentHTML('afterend', html);
                
                //Template über den Button setzen
                document.querySelector('#moreBtn').insertAdjacentHTML('beforebegin', html);
                
            }
    
        </script>


Funktion zum Erstellen einer neuen Tabellenzeile (in dieser wird summiert):

Code:
<script>
            
            function neueZeile() {
                
                const tabelle = document.getElementById('table1');
                const reihe = tabelle.insertRow(-1);
                
                for (var i = 0; i < 4; i++) {
                    
                    if(i == 0){
                        let inhalt = 'Reisetag/e',
                            zelle = reihe.insertCell();
                        i++;
                        
                        zelle.innerHTML = inhalt;
                    }
                    let inhalt = '0',
                        zelle = reihe.insertCell();
                        
                    zelle.innerHTML = inhalt;
                    
                }
                
                
            }
            
            
            
        </script>



Nun wird bisher so summiert:


Code:
<script>
            
            function copyValue(){
                
                //let regex = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
                
                var a = parseInt(document.getElementById('verpflegungspauschale1').value);
                var a1 = parseInt(document.getElementById('uebernachtung1').value);
                
                var str = document.querySelector("#table1_zelle2").innerHTML;
                var result = str.replace(str, a + a1);
                document.querySelector("#table1_zelle2").innerHTML = result;
                
                var b = parseInt(document.getElementById('teilnahmegebuehren1').value);
                
                var str2 = document.querySelector("#table1_zelle3").innerHTML;
                var result2 = str2.replace(str2, b);
                document.querySelector("#table1_zelle3").innerHTML = result2;
                
                var c = parseInt(document.getElementById('dienstwagen1').value);
                var c1 = parseInt(document.getElementById('busbahn1').value);
                var c2 = parseInt(document.getElementById('flugzeug1').value);
                var c3 = parseInt(document.getElementById('taxi1').value);
                
                var str3 = document.querySelector("#table1_zelle4").innerHTML;
                var result3 = str3.replace(str3, c + c1 + c2 + c3);
                document.querySelector("#table1_zelle4").innerHTML = result3;
            }
            
        
        </script>

Die Werte werden aus den Inputfeldern ausgelesen und kopiert. Danach summiert.
 
Werbung:

ZK_Crunchy

Mitglied
21 Januar 2021
45
0
6
24
Du kannst mit JavaScript Elemente auf ganz verschiedene Arten selektieren. Über ID wie du das versuchst, aber auch über Klassen oder über Element-Typ, etc. Da gibts viele Möglichkeiten, ich verwende mittlerweile kaum mehr die id.
Das stimmt. Das mit den Klassen ist mir auch bewusst. Aber entsteht dadurch nicht ein identisches Problem? Oder stört es html bzw js nicht, wenn eine Klasse erst später erstellt wird?
 

Sempervivum

Senior HTML'ler
18 Oktober 2016
2.192
434
83
68
Das mit den Klassen ist mir auch bewusst. Aber entsteht dadurch nicht ein identisches Problem? Oder stört es html bzw js nicht, wenn eine Klasse erst später erstellt wird?
Der Einwand ist berechtigt, denn eine Nodelist, die Du mit querySelectorAll erzeugst, ist nicht live, d. h. sie wird nicht aktualisiert, wenn Du ein Element später hinzu fügst.
Du weiß jedoch genau, wann das Hinzufügen passiert, nämlich beim Aufruf der Funktionen newDay und neueZeile. In diesen Funktionen kannst Du jeweils die Nodelist neu anlegen, dann hast Du immer den aktuellen Stand.
Ich schlage vor, Du gibst den Fieldsets für die Einzeldaten jeweils die selbe Klasse und ebenso den Zeilen in der Tabelle mit der Zusammenfassung eine andere. Dann kannst Du mit querySelectorAll für beide jeweils die Nodelist erzeugen. Dann in der Funktion copyValue über die erste Nodelist eine Schleife. Der Index ist dabei ja bekannt und Du kannst mit diesem Index auch auf die zweite Nodelist zugreifen. Da sowohl die Fieldsets als auch die Tabellenzeilen automatisch generiert werden, ist sicher gestellt, dass beide parallel aufgebaut sind.
 

ZK_Crunchy

Mitglied
21 Januar 2021
45
0
6
24
Der Einwand ist berechtigt, denn eine Nodelist, die Du mit querySelectorAll erzeugst, ist nicht live, d. h. sie wird nicht aktualisiert, wenn Du ein Element später hinzu fügst.
Du weiß jedoch genau, wann das Hinzufügen passiert, nämlich beim Aufruf der Funktionen newDay und neueZeile. In diesen Funktionen kannst Du jeweils die Nodelist neu anlegen, dann hast Du immer den aktuellen Stand.
Ich schlage vor, Du gibst den Fieldsets für die Einzeldaten jeweils die selbe Klasse und ebenso den Zeilen in der Tabelle mit der Zusammenfassung eine andere. Dann kannst Du mit querySelectorAll für beide jeweils die Nodelist erzeugen. Dann in der Funktion copyValue über die erste Nodelist eine Schleife. Der Index ist dabei ja bekannt und Du kannst mit diesem Index auch auf die zweite Nodelist zugreifen. Da sowohl die Fieldsets als auch die Tabellenzeilen automatisch generiert werden, ist sicher gestellt, dass beide parallel aufgebaut sind.
Das hört sich gut an! Leider habe ich sowas noch nie gemacht. Meine HTML Kenntnisse sind leider noch nicht so ausgereift. Könntest du mir einen Code Schnipsel zeigen, an den ich mich orientieren kann?
 
Werbung:

Sempervivum

Senior HTML'ler
18 Oktober 2016
2.192
434
83
68
Wenn ich mich richtig erinnere, hattest Du ja das Template verwendet. Bei diesem im äußersten Container eine einheitliche Klasse hinzu fügen:
Code:
<template id="new_passage">
        <fieldset style="width: 900;" class="reisetag" id="FeldTag{{nrtag}}" name="cloneTable">
            <!-- usw. -->
Bei der Tabelle mit der Zusammenfassung brauchen wir gar keine Klasse.
Dann die zwei Nodelists global anlegen:
Code:
let reisetageDetails, reisetageUebersicht;
Und in den beiden Funktionen jeweils die aktuelle Nodelist ermitteln:
Code:
            function newDay(addBtn){
                //Nummer des Tages erhöhen
                nrDay++;

                // usw. und dann ganz am Ende:

                reisetageDetails = document.querySelectorAll('.reisetag');
        }
Code:
            function neueZeile() {
               
                const tabelle = document.getElementById('table1');
                const reihe = tabelle.insertRow(-1);
               
                for (var i = 0; i < 4; i++) {
                   
                    if(i == 0){
                        let inhalt = 'Reisetag/e',
                            zelle = reihe.insertCell();
                        i++;
                       
                        zelle.innerHTML = inhalt;
                    }
                    let inhalt = '0',
                        zelle = reihe.insertCell();
                       
                    zelle.innerHTML = inhalt;
                   
                }
                reisetageUebersicht = document.querySelectorAll('#table1 tbody tr');
            }
Und beim Berechnen der Werte kannst Du die Listen dann verwenden:
Code:
            function copyValue(){
                reisetageDetails.forEach((detail, idx) => {
                    // Tabellenzeile in der Uebersicht bereit stellen:
                    uebersichtZeile = reisetageUebersicht[idx];
                    // Jetzt koennen wir auf die einzelnen Eingaberfelder zugreifen, z. B.:
                    const gebuehren = detail.querySelector('.gebuehren').value;
                    // usw.
                    // und in die Tabelle mit der Uebersicht eintragen:
                    uebersichtZeile.cells[0] = // hier der zuvor berechnete Wert
                });
            }
(alles ungetestet)
 

ZK_Crunchy

Mitglied
21 Januar 2021
45
0
6
24
Wow! Erst ein Mal einen riesen Dank an Dich! Nicht viele nehmen sich die Zeit um so ausführlich zu helfen.

Ich bin aktuell noch auf Achse. Ich setze ich alsbald dran und gebe Feedback!
 

ZK_Crunchy

Mitglied
21 Januar 2021
45
0
6
24
Hallo zusammen. Erst ein Mal sorry für die späte Rückmeldung. Ich hatte Freitag, gestern und heute Klausuren. Die Phase ist jetzt abgehakt und ich kann mich weiter mit dieser Angelegenheit beschäftigen.

Ich bin gerade dabei deinen Vorschlag zu schreiben und zu testen. Feedback kommt noch heute!
 
Werbung:

ZK_Crunchy

Mitglied
21 Januar 2021
45
0
6
24
Okay. Nun sieht es wie folgt aus:

Code:
<script>
            let nrDay = 1;
            let reisetageDetails, reisetageUebersicht;
       
            function newDay(addBtn){
               
                //Nummer des Tages erhöhren
                nrDay++;
               
                //HTML aus dem Template lesen
                let html = document.getElementById('new_passage').innerHTML;
               
                //Alle Vorkommen des Platzhalters, durch Nummer des Tages ersetzen
                html = html.replace(/{\{nrtag\}\}/g, nrDay);
               
                //Template einfügen
                //document.querySelector('.Feld3').insertAdjacentHTML('afterend', html);
               
                //Template über den Button setzen
                document.querySelector('#moreBtn').insertAdjacentHTML('beforebegin', html);
               
                reisetageDetails = document.querySelectorAll('.reisetag');
            }
   
        </script>

Die letzte Zeile wurde hinzugefügt.


Code:
<script>
           
            function neueZeile() {
               
                const tabelle = document.getElementById('table1');
                const reihe = tabelle.insertRow(-1);
               
                for (var i = 0; i < 4; i++) {
                   
                    if(i == 0){
                        let inhalt = 'Reisetag/e',
                            zelle = reihe.insertCell();
                        i++;
                       
                        zelle.innerHTML = inhalt;
                    }
                    let inhalt = '0',
                        zelle = reihe.insertCell();
                       
                    zelle.innerHTML = inhalt;
                   
                }
               
                reisetageUebersicht = document.querySelectorAll('#table1 tbody tr');
            }
           
           
           
        </script>

Auch hier wurde die letzte Zeile geschrieben.


Code:
<script>
           
            function copyValue(){
               
                //let regex = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
               
                var a = parseInt(document.getElementById('verpflegungspauschale1').value);
                var a1 = parseInt(document.getElementById('uebernachtung1').value);
               
                var str = document.querySelector("#table1_zelle2").innerHTML;
                var result = str.replace(str, a + a1);
                document.querySelector("#table1_zelle2").innerHTML = result;
               
                var b = parseInt(document.getElementById('teilnahmegebuehren1').value);
               
                var str2 = document.querySelector("#table1_zelle3").innerHTML;
                var result2 = str2.replace(str2, b);
                document.querySelector("#table1_zelle3").innerHTML = result2;
               
                var c = parseInt(document.getElementById('dienstwagen1').value);
                var c1 = parseInt(document.getElementById('busbahn1').value);
                var c2 = parseInt(document.getElementById('flugzeug1').value);
                var c3 = parseInt(document.getElementById('taxi1').value);
               
                var str3 = document.querySelector("#table1_zelle4").innerHTML;
                var result3 = str3.replace(str3, c + c1 + c2 + c3);
                document.querySelector("#table1_zelle4").innerHTML = result3;
               
            }
           
       
        </script>

Die Funktion habe ich bestehen gelassen. Diese füllt mir die erste Zeile der Tabelle aus.


Code:
<script>
       
            function copyValueGesamt(){
               
                reisetageDetails.forEach((detail, idx) => {
                   
                    //Tabellenzeile in der Uebersicht bereitstellen:
                    uebersichtZeile = reisetageUebersicht[idx];
                   
                    //Auf die einzelenen Eingabefelder zugreifen:
                    const verpflegung = parseFloat(document.formu.verpflegungspauschale1.value.replace(/,/ , ".") );
                    const uebernachtung = parseFloat(document.formu.uebernachtung1.value.replace(/,/ , ".") );
                    const summeVerpflegung = (verpflegung + uebernachtung);
                   
                   
                    uebersichtZeile.cells[0] = summeverpflegung;
                });
            }
           
       
       
        </script>

So sieht nun die neue Funktion aus. Diese funktioniert noch nicht. Ich bin in der Semantik noch nicht ganz durchgetiegen:

1. Was bedeutet reisetageDetails.forEach((detail, idx) => ....
Mit dem detail kann ich nichts anfangen. Idx ist ja der Index. Das ist klar. Muss ich diesen noch definieren?

2. //Auf die einzelnen Eingabefelder zugreifen.
Würde so mein Zugriff aussehen?

3. Ist das denn dynamisch? Sprich sobald ich das Formular erweitere und neue Werte eingebe, wird der Gesamtwert neu summiert?


Grüße
 

Sempervivum

Senior HTML'ler
18 Oktober 2016
2.192
434
83
68
1. Was bedeutet reisetageDetails.forEach((detail, idx) => ....
Mit dem detail kann ich nichts anfangen. Idx ist ja der Index. Das ist klar. Muss ich diesen noch definieren?
Die Funktion forEach arbeitet alle Elemente in reisetageDetails ab und ruft für jedes Element die anonyme Funktion auf, die mit dem Pfeiloperator definiert wird. detail ist jeweils das aktuelle Element aus der Nodelist und wird als erster Parameter an die Funktion übergeben. idx ist der Index des aktuellen Elementes.

2. //Auf die einzelnen Eingabefelder zugreifen.
Würde so mein Zugriff aussehen?
3. Ist das denn dynamisch? Sprich sobald ich das Formular erweitere und neue Werte eingebe, wird der Gesamtwert neu summiert?
So wie Du die Funktion copyValue geschrieben hast, ist es leider nicht dynamisch, denn Du hast feste IDs verwendet.
Sieh dir noch Mal meine Code in #10 an:
Code:
            function copyValue(){
                reisetageDetails.forEach((detail, idx) => {
                    // Tabellenzeile in der Uebersicht bereit stellen:
                    uebersichtZeile = reisetageUebersicht[idx];
                    // Jetzt koennen wir auf die einzelnen Eingaberfelder zugreifen, z. B.:
                    const gebuehren = detail.querySelector('.gebuehren').value;
                    // usw.
                    // und in die Tabelle mit der Uebersicht eintragen:
                    uebersichtZeile.cells[0] = // hier der zuvor berechnete Wert
                });
            }
Damit es dynamisch wird, müsstest Du dieses:
Code:
                var a = parseInt(document.getElementById('verpflegungspauschale1').value);
                var a1 = parseInt(document.getElementById('uebernachtung1').value);
so umändern:
Code:
var a = parseInt(detail.querySelector('.verpflegungspauschale').value);
var a1 = parseInt(detail.querySelector('.uebernachtung').value);
var summe = a + a1;
// Tabellenzeile in der Uebersicht bereit stellen:
uebersichtZeile = reisetageUebersicht[idx];
// und die Summe eintragen:
uebersichtZeile.cells[2] = summe;
// der Index 2 ist nur ein Beispiel, Du musst den verwenden, wo die Summe hin gehoert
Hier sucht detail.querySelector das Element mit der Klasse "verpflegungspauschale" bzw. "uebernachtung" auf und zwar innerhalb des Elementes detail, d. h. des aktuellen Elementes in der Nodelist.
Wobei ich voraus gesetzt habe, dass diesen Elementen diese Klasse auch zugewiesen wurde.
Die Summe wird dann in die Tabelle mit der Übersicht eingetragen.
 

ZK_Crunchy

Mitglied
21 Januar 2021
45
0
6
24
Okay, ich habe jetzt nochmal versucht da durch zu steigen. Und zwar ist mein Fehler, dass ich die Klassen noch nicht gesetzt habe. Weswegen .uebernachtung usw noch keinen Sinn für mich ergeben hat. Die Klassen schreibe ich in die entsprechenden Input-Felder?
 
Werbung:

Sempervivum

Senior HTML'ler
18 Oktober 2016
2.192
434
83
68
Genau, Du holst ja z. B. hiermit:
Code:
var a = parseInt(detail.querySelector('.verpflegungspauschale').value);
die Eingabe aus dem Input, daher musst Du die Klasse bei diesem setzen.
 

ZK_Crunchy

Mitglied
21 Januar 2021
45
0
6
24
Kurze finale Rückmeldung zum Thema: Aus Zeit gründen werde ich das Formular nicht weiter entwickeln. Daher habe ich auf eine statische Variante zurückgegriffen.
Das Einbinden des dynamischen Formular in die innerhalb eines Projektes entwickelte Software gestaltet sich als zeitintensiver als vorgesehen. Ich bedanke mich aber für die Hilfe :)
 
Werbung:

Neueste Beiträge