92 Stimmen

Verschachtelte optgroups in einer Dropdownliste/select

Ich habe ein benutzerdefiniertes c# DropDownList-Steuerelement erstellt, das seine Inhalte als optgroups rendern kann (Nicht von Grund auf neu, ich habe einige im Internet gefundenen Codes bearbeitet, obwohl ich genau verstehe, was es macht), und es funktioniert gut.

Allerdings bin ich nun auf eine Situation gestoßen, in der ich zwei Ebenen von Einrückungen in meinem Dropdown benötige, d.h.

     A.1 

       A.B.1 

     A.2 

Allerdings wird im obigen Beispiel-Snippet angezeigt, als wäre Ebene Zwei genauso eingerückt wie Ebene Eins.

Gibt es eine Möglichkeit, das verschachtelte optgroup-Verhalten zu erreichen, nach dem ich suche?

0 Stimmen

Hinzugefügt dieses Thema als Vorschlag an das HTMLWG: github.com/whatwg/html/issues/5789

1voto

AlexSp3 Punkte 2045

Verschachteltes Akkordeon-Auswahl

Ich habe diesen Ansatz gewählt, da ich nicht das gefunden habe, wonach ich gesucht habe. Ein verschachteltes Akkordeon-Auswahlfeld. Das CSS ist sehr einfach und kann verbessert werden. Das einzige, was Sie benötigen, ist ein Objekt mit Schlüsseln und Werten, die Sie dem Auswahlmenü hinzufügen möchten. Die Schlüssel sind Untergruppen, und die Schlüssel Werte (Arrays und einzelne Elemente) sind auswählbare Einträge.

Sobald Sie Ihr Array haben, müssen Sie nur noch folgendes aufrufen:

initAccordeon(obj);

mit Ihrem Datenobjekt als Argument, und das verschachtelte Akkordeon wird angezeigt:

const obj = {
  Cars: {
    SwedishCars: [
      "Volvo",
      "Saab"
    ],
    GermanCars: [
      "Mercedes",
      {
        Audi: [
          "Audi A3", 
          "Audi A4", 
          "Audi A5" 
        ]
      }
    ]
  },
  Food: {
    Fruits: [
      "Orange",
      "Apple",
      "Banana"
    ],
    SaltyFoods: [
      "Pretzels",
      "Burger",
      "Noodles"
    ],
    Drinks: "Water"
  }
};

initAccordeon(obj);   // <--------------------------- Aufruf der Initialisierung

function accordeonAddEvents() {
  Array.from(document.getElementsByClassName("accordeon-header")).forEach(function(header) {
    if (header.getAttribute("listener") !== "true") {
      header.addEventListener("click", function() {
        this.parentNode.getElementsByClassName("accordeon-body")[0].classList.toggle("hide");
      });
      header.setAttribute("listener", "true");
    }
  });

  Array.from(document.getElementsByClassName("button-group")).forEach(function(but) {
    if (but.getAttribute("listener") !== "true") {
      but.addEventListener("click", function() {
        if (this.getAttribute("depth") === "-1") {
          let header = this;
          while ((header = header.parentElement) && header.className !== "accordeon");
          header.getElementsByClassName("accordeon-header")[0].innerHTML = this.innerHTML;
          return;
        }
        const groups = Array.from(this.parentNode.getElementsByClassName("accordeon-group"));
        groups.forEach(g => {
          if (g.getAttribute("uuid") === this.getAttribute("uuid") &&
            g.getAttribute("depth") === this.getAttribute("depth")) {
            g.classList.toggle("hide");
          }
        });
      });
      but.setAttribute("listener", "true");
    }
  });
}

function initAccordeon(data) {
  accordeons = Array.from(document.getElementsByClassName("accordeon-body"));
  accordeons.forEach(acc => {
    acc.innerHTML = "";
    const route = (subObj, keyIndex = 0, parent = acc, depth = 0) => {
      const keys = Object.keys(subObj);
      if (typeof subObj === 'object' && !Array.isArray(subObj) && keys.length > 0) {
        while (keyIndex < keys.length) {
          var but = document.createElement("button");
          but.className = "button-group";
          but.setAttribute("uuid", keyIndex);
          but.setAttribute("depth", depth);
          but.innerHTML = keys[keyIndex];
          var group = document.createElement("div");
          group.className = "accordeon-group hide";
          group.setAttribute("uuid", keyIndex);
          group.setAttribute("depth", depth);
          route(subObj[keys[keyIndex]], 0, group, depth + 1);
          keyIndex++;
          parent.append(but);
          parent.append(group);
        }
      } else {
        if (!Array.isArray(subObj)) subObj = [subObj];
        subObj.forEach((e, i) => {
          if (typeof e === 'object') {
              route(e, 0, parent, depth);
          } else {
              var but = document.createElement("button");
              but.className = "button-group";
              but.setAttribute("uuid", i);
              but.setAttribute("depth", "-1");
              but.innerHTML = e;
              parent.append(but);
          }
        });
      }
    };
    route(data);
  });
  accordeonAddEvents();
}

.accordeon {
  width: 460px;
  height: auto;
  min-height: 340px;
  font-size: 20px;
  cursor: pointer;
  user-select: none;
  -moz-user-select: none;
  -khtml-user-select: none;
  -webkit-user-select: none;
  -o-user-select: none;
  display: block;
  position: relative;
  z-index: 10;
}

.accordeon-header {
  display: inline-block;
  width: 450px;
  border: solid 0.1vw black;
  border-radius: 0.2vw;
  background-color: white;
  padding-left: 10px;
  color: black;
}

.accordeon-header:hover {
  opacity: 0.7;
}

.accordeon-body {
  display: block;
  position: absolute;
}

.button-group {
  display: block;
  cursor: pointer;
  width: 460px;
  text-align: left;
  font-size: 20px;
  font-weight: bold;
}

.accordeon-group {
  padding-left: 20px;
}

.accordeon-group .button-group {
  width: 100%;
}

.button-group[depth="-1"] {
  color: green;
}

.hide {
  display: none;
}

  Etwas auswählen

1voto

Christopher Punkte 2114

Stand Ende 2021 gibt es immer noch keine Verschachtelung von .

Ich habe ein einfaches SCSS erstellt, das überhaupt kein Javascript erfordert. Für und um Optionen basierend auf auszurichten.

Es unterscheidet sich nur bei , die nicht mehr verwendet werden sollten. Verwenden Sie stattdessen

  1
  1,2
  20

  Weiß

/* kann leicht angepasst werden, um noch mehr zu unterstützen */
@for $i from 0 through 100 { 
  select[size] option.depth-#{$i},
  select[multiple] option.depth-#{$i} {
      padding-left: calc(0.2em + calc(0.8em * #{$i}));
  }
  /**
   * Das Label auf Optionen wird ähnlich behandelt wie  
   * (getestet mit Chrome 87 und 95)

   * Dies stellt eine  ähnlich einer Optionsgruppe dar
   * aber es erfordert das Attribut data-deppth und disabled
   */
  select[size] option.depth-#{$i}[label]:disabled, 
  select[multiple] option.depth-#{$i}[label]:disabled {
    font-weight: fett;
    color: initial;
  }
}

Beispiel-Fiddle

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X