Wie setze ich die display-property einer Liste auf none bzw. block in einem rekursiven Template?

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

Tabula_Rasa

Mitglied
12 Mai 2017
239
2
18
Hallo zusammen,

ich versuche via onclick die display-property zu ändern, jedoch weiß ich nicht, wie ich das entsprechende Element herausbekomme, um die display-property zu ändern.

Code:
        <ul *ngIf="children">
            <ng-container *ngTemplateOutlet="recursiveListTmpl; context:{ $implicit: children }"></ng-container>
        </ul>
         
          <ng-template #recursiveListTmpl let-children>
          <li *ngFor="let item of children; let i=index">
              {{item.name}}
              <ul *ngIf="item.children" class="sublists">
                  <ng-container *ngTemplateOutlet="recursiveListTmpl; context:{ $implicit: item.children }"></ng-container>
              </ul>
          </li>
          </ng-template>

Die Listen mit der class="sublists" sind nicht sichtbar, haben also display: none;
Das Problem ist, ich habe keine Idee wie ich via Onclick die Sichtbarkeit ändern soll.
Habt ihr einen Lösungsansatz, wie ich die richtige Liste anspreche und die display-property ändere?

Ich habe versucht spezifische Klassen den Listen zuzuordnen aber dann hatte ich mit dem Problem der Eindeutigkeit zutun, weil mehrere Listen dann dieselben Klassen hätten.
Ich wollte es dann mit der id versuchen aber da weiß ich nicht, wie ich die konkrete id als Argument in den ClickListener bekomme.

Hat jemand eine Idee, ohne die Objekte in children um eine property vom Typ boolean zu erweitern?
 
Zuletzt bearbeitet:

Tronjer

Senior HTML'ler
8 Oktober 2010
5.232
482
83
Berlin
Du könntest die Listen anhand einer Index Variable differenzieren. Jede Liste bekommt dann ein ng-class mit einer Expression, die als true oder false ausgewertet wird.
 
  • Like
Reaktionen: Tabula_Rasa

Tabula_Rasa

Mitglied
12 Mai 2017
239
2
18
Du könntest die Listen anhand einer Index Variable differenzieren. Jede Liste bekommt dann ein ng-class mit einer Expression, die als true oder false ausgewertet wird.

Aber wie sollte denn die Expression aussehen? Ich habe keine Idee, wie ich den Index nutzen könnte. Ich überlege mal, vielleicht fällt mir da was ein. Danke für die Hilfe.
 

Tabula_Rasa

Mitglied
12 Mai 2017
239
2
18
Ich finde nichts, womit ich die Liste, die durch den Klick angesprochen wird, anzeigen/verstecken kann. Wie sehe dein Ansatz mit dem Index denn aus? Wenn du Zeit hättest, wäre es nett von dir, mir da ein wenig weiterzuhelfen.
 

Tronjer

Senior HTML'ler
8 Oktober 2010
5.232
482
83
Berlin
Wie wäre es mit ElementRef? Obwohl es sicherlich noch bessere Ansätze gibt.
HTML:
<style>
  .hide {display: none;}
  .show {display: block;}
</style>

<div>
  <button (click)="onClick()">Click</button>
</div>

<ul #list>
  <li *ngFor="let el of elements;" class="hide">{{ el }}</li>
</ul>
Javascript:
export class AppComponent {
  public elements = ['foo', 'bar', 'baz'];
  @ViewChild('list', {static: false}) listRef: ElementRef<HTMLElement>;

  public onClick() {
    // show second list item
    this.listRef.nativeElement.children[1].classList.add('show');
  }
}
 
  • Like
Reaktionen: Tabula_Rasa

Tabula_Rasa

Mitglied
12 Mai 2017
239
2
18
Hey, danke für die Antwort. Sie hat mir weitergeholfen. Ich versuche jetzt das Element selbst als Argument zu übergeben, was auch ganz gut klappt bei den direct children von der Liste mit der Referenz list.
Das Problem ist aber, dass bei den indirect children ein Klick wie ein Doppelklick gewertet wird aber warum? Könntest du vielleicht folgenden Code inspizieren?

HTML:
         <ul #list *ngIf="children" id="recursiveList">
            <ng-container *ngTemplateOutlet="recList; context:{ $implicit: children }"></ng-container>
        </ul>
    
          <ng-template #recList let-children>
          <li *ngFor="let item of children;let i=index" (click)="toggleList($event)">
              {{item.name}}
              <ul *ngIf="item.children" class="hide">
                  <ng-container *ngTemplateOutlet="recList; context:{ $implicit: item.children }"></ng-container>
              </ul>
          </li>
          </ng-template>


Code:
  toggleList(e){
     let ul = e.target.children[0];
     console.log("Before: " + ul.classList);
     if(ul.classList.value == "hide"){
       ul.classList.remove("hide");
     } else {
       ul.classList.add("hide");
     }
     console.log("After: " + ul.classList);
}

Wenn ich auf einen indirect child drücke, also auf eine Liste die am Anfang noch die class="hide" hatte, steht Folgendes in der Console:
Code:
Before: Hide
After:
Before:
After: Hide

Als hätte ich einmal auf das Element gedrückt, wobei die Klasse Hide entfernt wurde und direkt danach wieder auf das Element gedrückt, wobei die Klasse Hide erneut hinzugefügt wurde, aber warum wird ein Klick auf das Element, auf ein indirect child, als ein Doppelklick gewertet?
 
Zuletzt bearbeitet:

Tronjer

Senior HTML'ler
8 Oktober 2010
5.232
482
83
Berlin
Doppelklick sicher nicht, aber die change detection wird vielleicht doppelt ausgeführt.

Ich würde auch einen anderen Ansatz wählen. Wenn ein Element nicht angezeigt werden soll, verbirgt man es nicht per CSS, sondern rendert es erst gar nicht.
 
  • Like
Reaktionen: Tabula_Rasa

Tabula_Rasa

Mitglied
12 Mai 2017
239
2
18
Aber dein Beispiel oben beinhaltet doch das Hinzufügen von CSS-Klassen? Oder war da ein anderer Ansatz, den du mir aufzeigen wolltest?