Как создать дерево отложенной загрузки в Angular 7 - PullRequest
6 голосов
/ 15 марта 2019

Я создаю TreeView с использованием Angular, и сценарий создания TreeView заключается в том, что у меня разные API для каждого уровня, значит, если я нажимаю на один из узлов родительского уровня, то только дочерний узел должен генерироваться только для этого конкретного узла и так далее длядальнейший уровень, и каждый список дочерних узлов исходит из API

. Теперь проблема заключается в том, что я создаю вложенный список для созданного представления дерева по щелчку любого узла.Дочерний узел генерируется для этого узла, а также для других узлов.

Вот мой код.

<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>

Примечание. Каждый список происходит из отдельного API, и эти события нажатия помогают вызывать API..

Пожалуйста, помогите мне с вышеуказанным вопросом заранее спасибо.

Ответы [ 2 ]

5 голосов
/ 18 марта 2019

Вы повторяете одни и те же вложенные списки для каждого вложенного ul.Вы должны связать ваши вложенные списки с их родителями .

Поскольку ваши элементы companyList и ваши элементы locationData имеют идентификатор, используйте этот идентификатор, чтобы связать вложенные списки с каждой компанией и с каждым местоположением.

Чтобы сделать связь, создайте карту в своем коде, используя простой объект, и введите ее с подписью индекса.В вашем случае это будет выглядеть примерно так:

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

Затем в вашем шаблоне вам нужно проиндексировать locationData и departmentData, используя item.id и 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>

Когда вы генерируете свои данные, поместите их под правильным идентификатором в объектах:

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;
  })
}

Вот пример с моделью данных Пользователь / Пост / Комментарий и API jsonplaceholder.

См. Демонстрацию Stackblitz для живого примера

<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;
    })
  }
}
2 голосов
/ 15 марта 2019

Вы можете отслеживать различные наборы данных по индексу их родителей в списке (идентификатор предпочтительнее, если элемент удаляется из списка, а индексы меняются, например)

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>
...