Je crée un TreeView à l'aide d'Angular et le scénario de création d'un treeview est que j'ai une API différente pour chaque niveau, ce qui signifie que si je clique sur l'un des nœuds de niveau parent, seul le nœud enfant doit générer pour ce nœud particulier et ainsi de suite pour le niveau supérieur et chaque liste de nœuds enfants provient de l'API

Maintenant, le problème est lorsque je crée une liste imbriquée dans l'arborescence créée, en cliquant sur n'importe quel nœud. Un nœud enfant est généré pour ce nœud et d'autres nœuds également.

Voici mon code.

<ul>
    <li *ngFor="let item of companyList" [id]="item.id">
        <span (click)="getLocation(item)">{{item.description}}</span>
      <ul>
          <li *ngFor="let loc of loactionData" [id]="loc.id">
          <span (click)="getDepartment(loc)">{{loc.description}}</span>
          <ul>
            <li *ngFor="let depart of deaprtmentData">
              <span (click)="getEmpStatus(depart)">{{depart.description}}</span>
            </li>
           </ul>
          </li>
    </ul>
  </li>
</ul>

Remarque : Chaque liste provient d'une API distincte et ces événements de clic permettent d'appeler l'API.

S'il vous plaît aidez-moi avec le problème ci-dessus merci d'avance.

7
VIVEK 15 mars 2019 à 14:07

2 réponses

Meilleure réponse

Vous répétez les mêmes listes imbriquées pour chaque ul imbriqué. Vous devez associer vos listes imbriquées à leurs parents.

Étant donné que vos éléments companyList et vos éléments locationData ont un identifiant, utilisez cet identifiant pour associer les listes imbriquées à chaque société et à chaque emplacement.

Pour faire l'association, créez une carte dans votre code à l'aide d'un objet simple et saisissez-la avec une signature d'index. Dans votre cas, cela ressemblera à ceci :

companyList: Company[] = [];
locationData: { [companyId: string]: Location[] } = {};
departmentData: { [locationId: string]: Department[] } = {};

Ensuite, dans votre modèle, vous devez indexer locationData et departmentData en utilisant item.id et loc.id :

<ul>
  <li *ngFor="let item of companyList" [id]="item.id">
    <span (click)="getLocation(item)">{{ item.description }}</span>
    <ul>
      <li *ngFor="let loc of locationData[item.id]" [id]="loc.id">
        <span (click)="getDepartment(loc)">{{ loc.description }}</span>
        <ul>
          <li *ngFor="let depart of departmentData[loc.id]">
            <span (click)="getEmpStatus(depart)">{{ depart.description }}</span>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

Lorsque vous générez vos données, placez-les sous le bon identifiant dans les objets :

getLocation(item: Company): void {
  this.http.get<Location[]>(`${this.api}/locations?companyId=${item.id}`).subscribe(locations => {
    this.locationData[item.id] = locations;
  })
}

getDepartment(location: Location): void {
  this.http.get<Department[]>(`${this.api}/departments?locationId=${location.id}`).subscribe(departments => {
    this.departmentData[location.id] = departments;
  })
}

Voici un exemple avec un modèle de données User/Post/Comment et l'API jsonplaceholder.

Voir cette démo Stackblitz pour un exemple en direct

<ul>
  <li *ngFor="let user of users" [id]="user.id">
    <span (click)="getPosts(user)">{{ user.name }}</span>
    <ul>
      <li *ngFor="let post of posts[user.id]" [id]="post.id">
        <span (click)="getComments(post)">{{ post.title }}</span>
        <ul>
          <li *ngFor="let comment of comments[post.id]">
            <span>{{ comment.name }}</span>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';

interface User {
  id: number;
  name: string;
  username: string;
  email: string;
}

interface Post {
  userId: number;
  id: number;
  title: string;
  body: string;
}

interface Comment {
  postId: number;
  id: number;
  name: string;
  email: string;
  body: string;
}

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
  users: User[] = [];
  posts: { [id: number]: Post[] } = {};
  comments: { [id: number]: Comment[] } = {};

  private api = 'https://jsonplaceholder.typicode.com';

  constructor(private http: HttpClient) { }

  ngOnInit(): void {
    this.http.get<User[]>(`${this.api}/users`).subscribe(users => this.users = users);
  }

  getPosts(user: User): void {
    this.http.get<Post[]>(`${this.api}/posts?userId=${user.id}`).subscribe(posts => {
      this.posts[user.id] = posts;
    })
  }

  getComments(post: Post): void {
    this.http.get<Comment[]>(`${this.api}/comments?postId=${post.id}`).subscribe(comments => {
      this.comments[post.id] = comments;
    })
  }
}
6
Community 20 juin 2020 à 09:12

Vous pouvez suivre les différents ensembles de données via l'index de leur parent dans la liste (l'identifiant serait préférable au cas où un élément serait supprimé de la liste et que les index changent par exemple)

public locationData = {};

load locationData(item, index):

this.locationData[index] = getDataForItem(item);

....

<ul>
            <li *ngFor="let item of companyList; let companyIndex = index;" [id]="item.id">
              <span (click)="getLocation(item, companyIndex)">{{item.description}}</span>
              <ul>
                <li *ngFor="let loc of loactionData[companyIndex]; let locationIndex = index;" [id]="loc.id">
                  <span (click)="getDepartment(loc, locationIndex)">{{loc.description}}</span>
                  <ul>
                    <li *ngFor="let depart of deaprtmentData[locationIndex]; let departmentIndex = index;">
                      <span (click)="getEmpStatus(depart, departmentIndex)">{{depart.description}}</span>

                    </li>
                  </ul>
                </li>
              </ul>
            </li>
          </ul>
2
Bert Maurau 15 mars 2019 à 11:12