2016-05-31 12 views
7

Ich habe eine App, die ich in Angular 2 (RC1) entwickeln. Das Menü muss aus der Datenbank erstellt werden. Daten werden über Web Api in JSON-Form geliefert. Ich möchte Menü aus den Daten rekursiv erstellen, um sicherzustellen, dass die Tiefe des Menüs kein Problem ist.Style in ngFor Schleife

Das Problem ist, wenn ich Klasse für bestimmte Zeile von ngFor Schleife hinzufügen möchte, und die Klasse wird zu allen Zeilen hinzugefügt, anstatt nur eine, die ich möchte.

Der Code ist auf der Suche etwas wie folgt aus:

sidenav.component.ts

import { Component, Input } from '@angular/core'; 
import { IMenu } from '../../../shared/models/menu.interface'; 
import { MenuComponent } from './menu.component'; 

@Component({ 
    moduleId: module.id, 
    selector: 'sidenav', 
    templateUrl: 'sidenav.component.html', 
    directives: [MenuComponent] 
}) 
export class SidenavComponent { 
    @Input() menu: IMeni[] 
} 

sidenav.component.html

... 
<menu-view [menu]="menu"></menu-view> 
... 

menu.component.ts

import { Component, Input } from '@angular/core'; 
import { IMenu } from '../../../shared/models/menu.interface'; 
@Component({ 
    moduleId: module.id, 
    selector: 'menu-view', 
    templateUrl: 'menu.component.html', 
    directives: [MenuComponent] 
}) 
export class MenuComponent { 
    isSelected: boolean = false; 
    @Input() meni: IMeni[]; 

    onSelect(): void { 
     this.isSelected = !this.isSelected; 
    } 
} 

menu.component.html

<ul> 
    <li *ngFor="let item of menu; let frst=first" 
      class="menu-list" 
      [ngClass]="{'active': 'isSelected', 'active': 'frst'}"> 

     <a [routerLink]="[item.uri]" (click)="onSelect()" > {{item.name}}</a> 

     <meni-view [menu]="item.children"></meni-view> 

    </li> 
</ul> 

Also, wenn ich auf die Eltern klicken, um alle Eltern aktiv werden, nicht nur, dass insbesondere ein, was befriedigend Verhalten sein. Was ich falsch mache?

+0

Was meinen Sie mit „auf Eltern klicken alle Eltern werden aktiv"? Sollte dies sein "klicken Sie auf Eltern alle' MenuComponent' werden aktiv "? –

+0

Wenn das Menü erstellt wird, gibt es eine Hierarchie von übergeordneten und untergeordneten Elementen. Nehmen wir an, das Modell für das Menü lautet: ID: Nummer; parentId: Nummer; Name: Zeichenfolge; Kinder: IMenu []; '. Wenn ich also auf die Elterninstanz des Menüelements klicke, öffne ich alle Instanzen der Elternmenüs. Das gewünschte Verhalten sollte sein, dass, wenn ich auf die Elterninstanz klicke, es sich öffnet, oder um nur die korrekte Klasse anzugeben, die mit Kindern des ausgewählten Elternteils blockiert werden soll. –

Antwort

10

Es scheint, wie Ihre Variable isSelected über die Liste geteilt wird. Ändern Sie die Variable, um stattdessen den Index zu verfolgen.

export class App { 
    menu = [{name: "Item 1", url: "/item1"}, {name: "Item 2", url: "/item2"},{name: "Item 3", url: "/item3"}]; 
    selectedIdx = 0; 

    selectItem(index):void { 
     this.selectedIdx = index; 
    } 
} 

machen es mit

<li *ngFor="let item of menu;let i = index" 
    class="menu-list" [ngClass]="{'active': selectedIdx == i}"> 
    <a (click)="selectItem(i)"> {{item.name}}</a> 
</li> 

Arbeiten http://plnkr.co/edit/7aDLNnhS8MQ1mJVfhGRR

+0

Danke, das ist genau das, was ich will. –

+0

Dank arbeiten wie der Himmel :) –

+0

Funktioniert wie ein Charme! Gute Antwort! – fauverism

3

Es gibt einige redundante '. Ich denke, man den Wert der Eigenschaft isSelected binden möchten nicht die 'isSelected' string (gleiche mit frst)

<li *ngFor="let item of menu; let frst=first" 
     class="menu-list" 
     [ngClass]="{'active': isSelected, 'active': frst}"> 
+0

Danke, aber ich habe ohne '' 'mit dem gleichen Ergebnis versucht. Ich schreibe weiter mit ''', weil es mir die Möglichkeit gibt, andere logische Fragen einzubeziehen, wie zum Beispiel: '[ngClass] =" {' nav-stacked ':' item.depth === 1 '} "'. –

+1

Warum sollte das mit '' 'besser funktionieren als ohne? –

+0

Diese spezielle Syntax ('[ngClass] =" {'nav-stacked': item.depth === 1} "') funktioniert nicht. –

2

ich eine Lösung habe (und es ist leicht), wenn Sie die JSON-Daten empfangen und in einer Variablen speichern von Ihnen (in Ihrem Fall heißt es menu) fügen Sie menu ein neues Feld namens Klassen und rendern es in der Vorlage!

Beispiel:

@Input() menu: IMenu[]; 
getMenu(){ 
    this.http.get(url).then(data => { 
    this.menu = data; 
    for(let i = 0; i < this.menu.length; i++) { 
     if(i == indexOfWantedElement){ 
     this.menu[i].classes = "myClass"; 
     continue; 
     } 
     this.menu[i].classes = ""; // others will have no classes 
    } 
    } 
} 

und in der Vorlage können Sie es leicht erlaufen machen

<ul> 
    <li *ngFor="let item of menu;" class="menu-list {{ item.classes }}"> 
    <a [routerLink]="[item.uri]" (click)="onSelect()" >{{item.name}}</a> 
    <meni-view [menu]="item.children"></meni-view> 
    </li> 
</ul> 
+0

Vielen Dank! Ich werde es mit Sicherheit versuchen. Ich werde immer noch nach der Antwort suchen, ohne noch einmal durch das Array zu laufen. –

+0

@ IgorIlić die Antwort von *** zaclerv ***, dass Sie ** verifiziert ** ist toll, aber es funktioniert nur auf Klick! Meine Antwort wird die Klasse zu mehreren Elementen hinzufügen und ohne das Click-Ereignis, das ist der Unterschied! jedenfalls viel Glück, fella :) –

0

hinzufügen #clickState zu Ihrer Zeile in der *ngFor

<row #clickState> 
    <i class="icon-cloud-download" 
     *ngIf="!clickState.clicked" 
     (click)="clickState.clicked=true"></i> 
    <i class="fa fa-spinner" 
     *ngIf="clickState.clicked 
     (click)="clickState.clicked=false"></i> 
</row> 
Verwandte Themen