Auswertung von checkboxen

Stuhlbein

Mitglied
So deklariere ich eine Gruppe von vier checkboxen:
Java:
 <div class="block">
        <h3>Wohnungsmerkmale:</h3>
        <label><input type="checkbox" id="merkmal1"> Appartement </label><br>
        <label><input type="checkbox" id="merkmal2"> Maisonette- oder Galerie-Wohnung </label><br>
        <label><input type="checkbox" id="merkmal3"> Dachgeschoss-Wohnung </label><br>
        <label><input type="checkbox" id="merkmal4"> Souterrain-Wohnung </label>
    </div>

Eine angeklickte checkbox wird aber nicht richtig verarbeitet:
Code:
<script>
        // Globale Variablen
        let ug = 0.00;
        let mw = 0.00;
        let og = 0.00;

      
            // Block 3 - Wohnungsmerkmale auswerten
            if (document.getElementById("merkmal1").checked) {
                ug += 0.54; mw += 0.54; og += 0.54;
            }
            if (document.getElementById("merkmal2").checked) {
                ug += 0.07; mw += 0.07; og += 0.07;
            }
            if (document.getElementById("merkmal3").checked) {
                ug += 0.05; mw += 0.05; og += 0.05;
            }
            if (document.getElementById("merkmal4").checked) {
                ug -= 0.09; mw -= 0.09; og -= 0.09;
            }

Wo liegt der Haken, dass die Variablen sich nicht verändern bzw. die checkbox nicht richtig erkannt wird? Oder sind das zu wenig Info?
 

KonradN

Super-Moderator
Mitarbeiter
Du hast das einfach nur direkt im Script-Tag? Dann wird es direkt beim/nach dem Laden ausgeführt und da ist dann nichts ausgewählt.

Damit etwas aktiv passiert, müsste es in einem Event ausgeführt werden, also wenn der Nutzer etwas gemacht hat. So könntest Du den checkboxen einen EventListener hinzu fügen, der auf die Auswahl oder das Aufheben der Auswahl reagiert.

Aber evtl. habe ich Dich auch einfach missverstanden, da der Code halt recht minimal und stark gekürzt ist und nicht ersichtlich ist, was Du wann wie machen willst.
 

Oneixee5

Top Contributor
Abgesehen von der Behandlung der Events ist es üblich bei Checkboxen und Radioboxen jedem input-Element ein value-Attribut mitzugeben. Mit dem Wert aus dem value-Attribut kann man dann seine Daten ansprechen. Das verringert die Anzahl der if-Konstrukte erheblich.
Du musst auch beachten, was passiert wenn du mit Dezimalzahlen arbeitest. Es bietet sich auch an, statt X Variablen einzeln zu verwalten, diese in Objekten zusammenzufassen, bspw. um die Zusammengehörigkeit darzustellen oder wenn du diese mal ein eine Funktion übergeben willst.

HTML:
<html>
  <head>
    <title>Wohnungsmerkmale:</title>

    <script>
      // Apartment features data structure
      const data = {
        apparment: { ug: 0.54, mw: 0.54, og: 0.54 },
        maisonette: { ug: 0.07, mw: 0.07, og: 0.07 },
        topFloor: { ug: 0.05, mw: 0.05, og: 0.05 },
        souterrain: { ug: -0.09, mw: -0.09, og: -0.09 },
      };

      // Result object
      const result = {
        ug: 0,
        mw: 0,
        og: 0,
      };

      /**
       * Update the result values in the DOM (HTML)
       */
      const updateResutls = () => {
        for (const [key, value] of Object.entries(result)) {
          // @see <p>Untergeschoss: <span id="ug">0</span></p> -> key = "ug", value = 0
          document.getElementById(key).innerText = value;
        }
      };

      /**
       * Add two numbers and round the result to two decimal places
       * @param {number} a
       * @param {number} b
       * @returns {number}
       */
      const addDecimal = (a, b) => Math.round((a + b) * 100) / 100;

      /**
       * Subtract two numbers and round the result to two decimal places
       * @param {number} a
       * @param {number} b
       * @returns {number}
       */
      const subtractDecimal = (a, b) => Math.round((a - b) * 100) / 100;

      /**
       * Handle checkbox click event
       * @param {Event} event
       */
      const handleCheckboxClick = (event) => {
        const { checked, value } = event.target;
        if (checked) {
          result.ug = addDecimal(result.ug, data[value].ug);
          result.mw = addDecimal(result.mw, data[value].mw);
          result.og = addDecimal(result.og, data[value].og);
        } else {
          result.ug = subtractDecimal(result.ug, data[value].ug);
          result.mw = subtractDecimal(result.mw, data[value].mw);
          result.og = subtractDecimal(result.og, data[value].og);
        }
        updateResutls();
      };

      // Add event listener to all checkboxes
      document.addEventListener("DOMContentLoaded", () => {
        const checkboxes = document.querySelectorAll('input[type="checkbox"]');

        checkboxes.forEach((checkbox) => {
          checkbox.addEventListener("click", handleCheckboxClick);
        });
      });
    </script>
  </head>

  <body>
    <div class="block">
      <h3>Wohnungsmerkmale:</h3>
      <label>
        <input type="checkbox" id="merkmal1" value="apparment" />
        Appartement
      </label>
      <br />
      <label>
        <input type="checkbox" id="merkmal2" value="maisonette" />
        Maisonette- oder Galerie-Wohnung
      </label>
      <br />
      <label>
        <input type="checkbox" id="merkmal3" value="topFloor" />
        Dachgeschoss-Wohnung
      </label>
      <br />
      <label>
        <input type="checkbox" id="merkmal4" value="souterrain" />
        Souterrain-Wohnung
      </label>
    </div>

    <div class="block">
      <h3>Ergebnis:</h3>
      <p>Untergeschoss: <span id="ug">0</span></p>
      <p>Mittelgeschoss: <span id="mw">0</span></p>
      <p>Obergeschoss: <span id="og">0</span></p>
    </div>
  </body>
</html>

handleCheckboxClick könnte man mit der gleichen for-Schleife verarbeiten wie in updateResutls - ich wollte es aber nicht zu unübersichtlich machen:
Javascript:
for (const [key, value] of Object.entries(result)) { ... }
 
Zuletzt bearbeitet:

Stuhlbein

Mitglied
Danke, das hat mir weitergeholfen. Ich habe zwar nicth alles verwendet, aber der code läuft nun einwandfrei.
Nun habe ich eine weitere Frage.
So frage ich Wohnunungsgrößen ab:
Java:
// dropdown Wohnungsgröße
            switch (wohnungsgröße) {
                case "20,00 bis 25 m²":
                    diff = 1.74; ug += diff; mw += diff; og += diff; break;
                case "25,01 bis 30 m²":
                    diff = 1.29; ug += diff; mw += diff; og += diff; break;
                case "30,01 bis 35 m²":
                    diff = 1.28; ug += diff; mw += diff; og += diff; break;
                case "35,01 bis 40 m²":
                    diff = 0.92; ug += diff; mw += diff; og += diff; break;
                case "40,01 bis 45 m²":
                    diff = 0.57; ug += diff; mw += diff; og += diff; break;
                case "45,01 bis 50 m²":
                    diff = 0.44; ug += diff; mw += diff; og += diff; break;
                case "50,01 bis 60 m²":
                    diff = 0.20; ug += diff; mw += diff; og += diff; break;
                case "60,01 bis 80 m²":
                    diff = 0; break; // Keine Änderung                   
                case "80,01 bis 110 m²":
                    diff = -0.05; ug += diff; mw += diff; og += diff; break;
                case "110,01 bis 145 m²":
                    diff = -0.13; ug += diff; mw += diff; og += diff; break;
            }       
            message += `Sie haben eine Wohnungsgröße von ${wohnungsgröße} ausgewählt.<br>`;
            if (diff < 0) {
                const formattedDiff = Math.abs(diff).toFixed(2).replace('.', ',');
                message += `Dadurch ergibt sich ein Preisabschlag von ${formattedDiff} € je m².<br>`;
            } else if (diff == 0) {
                message += `Diese Größe führt weder zu einem Mietzu- noch -abschlag.<br>`;
            } else {
                const formattedDiff = diff.toFixed(2).replace('.', ',');
                message += `Dadurch ergibt sich ein Mietzuschlag von ${formattedDiff} € je m².<br>`;
            }

Wenn nun eine Wohngsgröße ausgewählt wurde, die größer als 50 qm ist, darf die nachfolgende checkbox nicht anklickbar sein, da sie nur für Appartements gilt und die sind max. 50 qm groß:
Code:
//ist ein Appartement vorhanden? Kann nur zutreffen, wenn Wohnung max. 50 qm groß
if (document.getElementById("checkboxM1").checked) {
                diff = 0.54; ug += diff; mw += diff; og += diff;
                const formattedDiff = diff.toFixed(2).replace('.', ',');
                message += `<br>Sie haben angegeben, dass es sich bei Ihrer Wohnung um ein Appartement handelt. Dadurch erhöht sich der Preis um ${formattedDiff} € je m².<br>`;
            }

So habe ich versucht, das Problem zu lösen, aber die checkbox lässt sich weiterhin anklicken:
Code:
// Aktivieren oder Deaktivieren der Checkbox
const checkboxM1 = document.getElementById("checkboxM1");
if (wohnungsgröße === "20,00 bis 25 m²" || wohnungsgröße === "25,01 bis 30 m²" ||
    wohnungsgröße === "30,01 bis 35 m²" || wohnungsgröße === "35,01 bis 40 m²" ||
    wohnungsgröße === "40,01 bis 45 m²" || wohnungsgröße === "45,01 bis 50 m²") {
    checkboxM1.disabled = false; // Checkbox aktivieren
} else {
    checkboxM1.checked = false; // Checkbox zurücksetzen
    checkboxM1.disabled = true;  // Checkbox deaktivieren
}

Was mache ich falsch?
 

Oneixee5

Top Contributor
Es gibt bereits ein switch-case wozu dann der extra if-Block um die 'wohnungsgröße' abzufragen?
Der wiederholte Aufruf von document.getElementById macht eine Webseite auch nicht gerade schneller. Moderne Browser können das zwar relativ gut aber man tut das trotzdem nicht. Man kann ja auch Listener verwenden. Warum das letzte if-else nicht funktioniert ist für mich aus dem gezeigten Code nicht ersichtlich. Es kann sein, dass die verwendete ID mehrfach im HTML vorkommt und deshalb ein falsches Element gefunden wird.
Nochwas:
Variablennamen mit Umlauten und ß geht gar nicht. Auch wenn es bei deinem Projekt vermutlich keinen beteiligten mit ausländischem Tastaturlayout gibt, fängt man so ein Unsitte gar nicht erst an.
Diese Orgien aus switch-case und if-else solltest du dir schnell abgewöhnen. Der Code wird nicht nur langsam sondern auch riesig groß aufbläht und unübersichtlich. Verwende Listener und data-Attribute. Textvergleiche wie 'wohnungsgröße === "20,00 bis 25 m²"' sind sehr ungünstig, besonders wenn sie öfter durchgeführt werden. Stell dir einfach vor, du muss jeden Monat die Texte anpassen, bspw. statt 2 nur eine Nachkommastelle. Wie viele Stellen im Programm musst du dann anpassen? Erstelle dir Objekte mit einem eindeutigen Key und Text, inkl. der anderen Eigenschaften, dass können in JS auch Funktionen sein. So müsstest du nur an einer Stelle den Text ändern oder kannst für jeden Wert angepasste Funktionen aufrufen - einfach per ID.
Du solltest also an deinem Verständnis arbeiten, was unter Programmierung zu verstehen ist.
 

Neue Themen


Oben