调用
<!-- 单位树型菜单 -->
<app-tree [list]="org_list" name_field="ORG_FULLNAME"
(onChange)="selectOrg($event)">
</app-tree>
组件tree
tree.component.html
<div class="tree-container {{cssClass}}">
<ng-container *ngFor="let item_lv1 of list;let i = index;" >
<!-- 1级菜单 -->
<div class="item item-lv1" [class.selected]="node_selected == item_lv1" (click)="selectNode(i)" >
<ion-icon [class.hide]="!item_lv1.children || !item_lv1.children.length" *ngIf="!item_lv1.expand" name="{{ion_fold}}"></ion-icon>
<ion-icon [class.hide]="!item_lv1.children || !item_lv1.children.length" *ngIf="item_lv1.expand" name="{{ion_expand}}"></ion-icon>
<span>{{item_lv1[name_field]}}({{item_lv1.children.length}})</span>
<ion-button *ngIf="btn_text && !item_lv1.IS_AUTO" fill="outline" (click)="clickButton($event, item_lv1)">{{item_lv1.IS_SIGN ? btn_text_signed : btn_text }}</ion-button>
</div>
<!-- 子菜单: 2级 -->
<div class="list-lv2" *ngIf="item_lv1.expand">
<ng-container *ngFor="let item_lv2 of item_lv1.children;let j = index;" >
<div class="item item-lv2" [class.selected]="node_selected == item_lv2" (click)="selectNode(i, j)">
<ion-icon [class.hide]="!item_lv2.children || !item_lv2.children.length" *ngIf="!item_lv2.expand" name="{{ion_fold}}"></ion-icon>
<ion-icon [class.hide]="!item_lv2.children || !item_lv2.children.length" *ngIf="item_lv2.expand" name="{{ion_expand}}"></ion-icon>
<span>
<i *ngIf="show_sn">{{j+1}}</i>
{{item_lv2[name_field]}}
</span>
<ion-button *ngIf="btn_text && !item_lv2.IS_AUTO" fill="outline" (click)="clickButton($event, item_lv2)">{{item_lv2.IS_SIGN ? btn_text_signed : btn_text }}</ion-button>
<ion-button *ngIf="item_lv2.IS_AUTO" fill="outline" class="auto-sign">自动打卡</ion-button>
</div>
<!-- 3级 -->
<div class="list-lv3" *ngIf="item_lv2.expand">
<ng-container *ngFor="let item_lv3 of item_lv2.children;let k=index;">
<div class="item item-lv3" [class.selected]="node_selected == item_lv3" (click)="selectNode(i, j, k)">
<ion-icon [class.hide]="!item_lv3.children.length" *ngIf="!item_lv3.expand" name="{{ion_fold}}"></ion-icon>
<ion-icon [class.hide]="!item_lv3.children.length" *ngIf="item_lv3.expand" name="{{ion_expand}}"></ion-icon>
<span>
<i *ngIf="show_sn">{{j+1}}.{{k+1}}</i>
{{item_lv3[name_field]}}
</span>
</div>
<!-- 4级 -->
<div class="list-lv4" *ngIf="item_lv3.expand">
<ng-container *ngFor="let item_lv4 of item_lv3.children;let l=index;">
<div class="item item-lv4" [class.selected]="node_selected == item_lv4"
(click)="selectNode(i, j, k, l)">
<ion-icon [class.hide]="!item_lv4.children.length" *ngIf="!item_lv4.expand" name="{{ion_fold}}"></ion-icon>
<ion-icon [class.hide]="!item_lv4.children.length" *ngIf="item_lv4.expand" name="{{ion_expand}}"></ion-icon>
<span>
<i *ngIf="show_sn">{{j+1}}.{{k+1}}.{{l+1}} </i>
{{item_lv4[name_field]}}</span>
</div>
<!-- 5级 -->
<div class="list-lv5" *ngIf="item_lv4.expand">
<ng-container *ngFor="let item_lv5 of item_lv4.children;let m=index;">
<div class="item item-lv5" [class.selected]="node_selected == item_lv5"
(click)="selectNode(i, j, k, l,m)">
<ion-icon [class.hide]="!item_lv5.children.length" *ngIf="!item_lv5.expand" name="{{ion_fold}}"></ion-icon>
<ion-icon [class.hide]="!item_lv5.children.length" *ngIf="item_lv5.expand" name="{{ion_expand}}"></ion-icon>
<span>
<i *ngIf="show_sn">{{j+1}}.{{k+1}}.{{l+1}}.{{m+1}}</i>
{{item_lv5[name_field]}}</span>
</div>
<!-- 6级 -->
<div class="list-lv6" *ngIf="item_lv5.expand">
<ng-container *ngFor="let item_lv6 of item_lv5.children;let n=index;">
<div class="item item-lv6" [class.selected]="node_selected == item_lv6"
(click)="selectNode(i, j, k, l,m, n)">
<ion-icon [class.hide]="!item_lv6.children.length" *ngIf="!item_lv6.expand" name="{{ion_fold}}"></ion-icon>
<ion-icon [class.hide]="!item_lv6.children.length" *ngIf="item_lv6.expand" name="{{ion_expand}}"></ion-icon>
<span>
<i *ngIf="show_sn">{{j+1}}.{{k+1}}.{{l+1}}.{{m+1}}.{{n+1}} </i>
{{item_lv6[name_field]}}
</span>
</div>
</ng-container>
</div>
</ng-container>
</div>
</ng-container>
</div>
</ng-container>
</div>
</ng-container>
</div>
</ng-container>
</div>
tree.component.scss
.tree-container {
.item {
padding: 8px 16px 8px 0;
display: flex;
align-items: center;
border-bottom: 1px solid #d2d2d2;
&.selected {
background-color: #eaeaea;
}
ion-icon {
color: #aaaaaa;
margin: 0 10px;
&.hide {
opacity: 0;
}
}
span {
width: min-content;
flex: 1 0 auto;
font-size: 14px;
}
}
.item-lv2 {
padding-left: 14px !important;
}
.item-lv3 {
padding-left: 28px !important;
}
.item-lv4 {
padding-left: 42px !important;
}
.item-lv5 {
padding-left: 56px !important;
}
.item-lv6 {
padding-left: 70px !important;
}
[name="chevron-down-outline"],
[name="chevron-up-outline"] {
display: none;
}
}
tree.component.ts
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-tree',
templateUrl: './tree.component.html',
styleUrls: ['./tree.component.scss'],
})
export class TreeComponent implements OnInit {
@Input() list;
@Input() name_field;
@Input() cssClass='';
@Input() btn_text=''; //按钮文本
@Input() btn_text_signed=''; //按钮文本
@Input() show_sn; //是否显示序号
@Input() ion_fold = 'caret-forward-outline'; //是否显示序号
@Input() ion_expand = 'caret-down-outline'; //是否显示序号
@Output() onChange = new EventEmitter();
@Output() onButtonClick = new EventEmitter();
node_selected = {};
constructor() { }
ngOnInit() {
this.name_field = this.name_field ? this.name_field : 'name';
this.show_sn = this.show_sn ? this.show_sn : false;
}
// 选择一个节点
selectNode(i = null, j = null, k = null, l = null, m = null, n = null) {
if (n != null) {
// 点击的第6级
this.node_selected = this.list[i].children[j].children[k].children[l].children[m].children[n];
this.list[i].children[j].children[k].children[l].children[m].children[n].expand = !this.list[i].children[j].children[k].children[l].children[m].children[n].expand;
} else if (m != null) {
// 点击的第5级
this.node_selected = this.list[i].children[j].children[k].children[l].children[m];
this.list[i].children[j].children[k].children[l].children[m].expand = !this.list[i].children[j].children[k].children[l].children[m].expand;
} else if (l != null) {
// 点击的第4级
this.node_selected = this.list[i].children[j].children[k].children[l];
this.list[i].children[j].children[k].children[l].expand = !this.list[i].children[j].children[k].children[l].expand;
} else if (k != null) {
// 点击的第3级
this.node_selected = this.list[i].children[j].children[k];
this.list[i].children[j].children[k].expand = !this.list[i].children[j].children[k].expand;
} else if (j != null) {
// 点击的第2级
this.node_selected = this.list[i].children[j];
this.list[i].children[j].expand = !this.list[i].children[j].expand;
} else if (i != null) {
// 点击的第1级
this.node_selected = this.list[i];
this.list[i].expand = !this.list[i].expand;
}
this.onChange.emit(this.node_selected);
}
clickButton(event, item) {
// console.log(event, item);
this.onButtonClick.emit({event, item});
}
}