首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >角8-递归实现具有动态展开和折叠的层次列表。

角8-递归实现具有动态展开和折叠的层次列表。
EN

Stack Overflow用户
提问于 2020-05-20 04:36:07
回答 1查看 862关注 0票数 0

我正在尝试构建一个分层展开/折叠列表来表示父级子关系。在初始加载时,将列出父节点。如果他们有孩子,则会显示一个克拉图标,否则就会显示一个子弹图标。单击克拉图标后,将发出API调用来检索数据,并显示子信息。再次单击同一克拉图标时,将不会进行API调用,但直接子列表将被隐藏。如果子节点是父节点,则应该递归地发生这种情况。

期望的初始加载行为:

单击克拉图标以展开:需要的行为:

JSON数据

代码语言:javascript
运行
复制
{
    "page": {
        "results": [{
            "id": "1001",
            "title": "American",
            "children": {
                "page": {
                    "results": [{
                        "id": "1003",
                        "title": "Chevy",
                        "children": {
                            "page": {
                                "results": [],
                                "start": 0,
                                "limit": 25,
                                "size": 0
                            }
                        }
                    }],
                    "start": 0,
                    "limit": 25,
                    "size": 1
                }
            }
        }, {
            "id": "1002",
            "title": "German",
            "children": {
                "page": {
                    "results": [],
                    "start": 0,
                    "limit": 25,
                    "size": 0
                }
            }
        }],
        "start": 0,
        "limit": 2,
        "size": 2
    }
}

组件代码

代码语言:javascript
运行
复制
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/throw';

import { WikiService } from '../wiki.service';
import { WikiTree } from '../../interfaces/WikiTree';
import { AppConfigService } from '../../services/app-config.service';

@Component({
  selector: 'app-wiki-tree-nav',
  templateUrl: './wiki-tree-nav.component.html',
  styleUrls: ['./wiki-tree-nav.component.css']
})
export class WikiTreeNavComponent implements OnInit {

  public wikiPageId: any = '1000';
  wikiTree$: Observable<WikiTree>;
  public resultsPage: any;

  constructor(private wikiService: WikiService, private route: ActivatedRoute,
    private appConfigService: AppConfigService) {
    this.route.params.subscribe(res => this.wikiPageId = res.id);
  }

  ngOnInit() {
      this.getWikiTree(0, 200, this.wikiPageId);
  }

  getWikiTree(start: number = 0, limit: number = 200, pageId: string = '') {
    this.wikiTree$ = this.wikiService.GetWikiTree(start, limit, pageId);
    this.wikiTree$.subscribe((data) => {
      this.resultsPage = data;
    },
      (err) => {
      }
    );
  }

  getCSSClass(pageId: string) {
    let cssClass = '';
    if (this.wikiPageId === pageId) {
      cssClass = 'boldTitle';
    }
    return cssClass;
  }

}

HTML代码

代码语言:javascript
运行
复制
<ul *ngIf="wikiTree$ | async as wikiTree">
        <li *ngFor="let result of wikiTree.page.results; index as i" style="margin-bottom:10px;">
            <div>
                <span *ngIf="result.children.page.size==0" style="margin-left:4px;margin-right:4px;">
                    <clr-icon shape="circle" class="is-solid" size="6"></clr-icon>
                </span>
                <span *ngIf="result.children.page.size>0">
                    <a (click)="getWikiTree(0,200,result.id)">
                        <clr-icon shape="caret right" size="14"></clr-icon>
                    </a>
                </span>
                <span style="margin-left:5px;font-size:14px;" [ngClass]="getCSSClass(result?.id)">
                    <a href="/pages/{{result.id}}">{{result.title}}</a>
                </span>
            </div>
        </li>
    </ul>

我的当前HTML代码替换了整个树,而不是附加到父节点。如何实现角HTML代码来递归地执行展开和折叠?

EN

回答 1

Stack Overflow用户

发布于 2020-05-20 11:12:12

我去创建一个结构指令,所以我的app.component.html变成了

代码语言:javascript
运行
复制
<div recursive [children]="data" [search]="dataService.getData"></div>

在这里我定义了

代码语言:javascript
运行
复制
  constructor(public dataService:DataService){}
  ngOnInit()
  {
    this.dataService.getData(0).subscribe(res=>this.data=res)
  }

我需要将"search“函数传递给递归组件,该组件返回一个可观察到的对象数组,对象具有属性'id‘、'label’和'hasChildren‘,以指示是否有子对象,例如,json响应类似于

代码语言:javascript
运行
复制
[{id:1,label:'label1',hasChildren:true},{id:2,label:'label2'}]

在递归组件中,我喜欢定义为@Input()级别、子级和父级。正如您想要的那样,在单击获取“子”的函数时,我添加搜索,并在“打开”函数中更改属性"isOpen“并调用searchFunction。请注意,在管理组件的对象中,最初没有属性“子”或“isOpen”,我添加了以下“动态”

代码语言:javascript
运行
复制
@Component({
  selector: "[recursive]",
  templateUrl: "./tree-view.component.html",
  styleUrls: ["./tree-view.component.css"]
})
export class TreeViewComponent {
  @Input() level: number;
  @Input() children: any;
  @Input() parent: any;

  @Input() search: (any) => Observable<any>;

  self = this;
  open(item) {
    item.isOpen = !item.isOpen;
    if (!item.children) {
      item.loading="...."
      this.search(item.id).subscribe(res=>{
        item.loading=null
        item.children=res;
      })
    }
  }
}

在这种情况下,我们的树-view.html如下

代码语言:javascript
运行
复制
<ul class="tree" *ngIf="level==undefined">
  <ng-container *ngTemplateOutlet="tree;context:{children:children,search:search}">
  </ng-container>
</ul>
<ng-container *ngIf="level!=undefined">
  <ng-container *ngTemplateOutlet="tree;context:{children:children,search:search}">
  </ng-container>
</ng-container>

<ng-template #tree let-children="children" let-search="search">
<li *ngFor="let item of children">
    <div (click)="item.hasChildren && open(item)">
     <span [ngClass]="!item.hasChildren?'doc':item.isOpen?'open':'close'" ></span>
     {{item.label}}{{item.loading}}
  </div>
    <ul recursive *ngIf="item.children && item.isOpen" 
        [children]="item.children" 
        [parent]="self" 
        [level]="level!=undefined?level+1:0"
        [search]="search"
        >
  </ul>
</li>
</ng-template>

stackblitz,我希望这对你有帮助

注意:我使用三个css类,.doc、.open和.close来指示树的状态,以及使用of和delay的“傻瓜”服务来模拟调用。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61905207

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档