简体   繁体   English

如何在Angular 7中创建延迟加载树视图

[英]How to create a lazy load treeview in Angular 7

I am creating a TreeView using Angular and the scenario of creating treeview is I have different API for each level means if I click on one of the parent level nodes then only child node should generate for that particular node only and so on for further level and every child node list is coming from API 我正在使用Angular创建一个TreeView,并且创建treeview的场景是我对每个级别都有不同的API意味着如果我单击其中一个父级别节点,那么只有子节点应该仅为该特定节点生成,依此类推以获得更高级别和每个子节点列表都来自API

Now the issue is when I'm creating a nested list to the created tree view, on the click of any node. 现在问题是当我在创建的树视图中创建嵌套列表时,单击任何节点。 A child node is generating for that node and other nodes also. 子节点也为该节点和其他节点生成。

Here is my 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>

Note: Every list is coming from separate API and these click event helps to call API. 注意:每个列表都来自单独的API,这些点击事件有助于调用API。

Please help me with the above issue thanks in advance. 请提前感谢您帮助我解决上述问题。

You are repeating the same nested lists for each nested ul . 您正在为每个嵌套的ul重复相同的嵌套列表。 You have to associate your nested lists to their parents . 您必须将嵌套列表与其父项关联

Since your companyList items and your locationData items have an id, use this id to associate the nested lists to each company and to each location. 由于您的companyList项目和您的locationData项目具有ID,因此请使用此ID将嵌套列表与每个公司和每个位置相关联。

To do the association, create a map in your code using a simple object and type it with an index signature. 要进行关联,请使用简单对象在代码中创建一个映射,并使用索引签名键入它。 In your case it will look something like this: 在你的情况下,它看起来像这样:

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

Then in your template, you need to index locationData and departmentData using item.id and loc.id : 然后在模板中,您需要使用item.idloc.id索引locationDatadepartmentData

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

When you generate your data, place it under the right id in the objects: 生成数据时,将其放在对象中的正确ID下:

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

Here is an example with a User/Post/Comment data model and the jsonplaceholder API. 以下是User / Post / Comment数据模型和jsonplaceholder API的jsonplaceholder

See this Stackblitz demo for a live example 有关实例,请参阅此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;
    })
  }
}

You could keep track of the different datasets via their parent's index in the list (id would be prefered in case an item gets deleted from the list and the indexes change for example) 您可以通过列表中的父级索引跟踪不同的数据集(如果项目从列表中删除并且索引更改,则会优先使用id)

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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM