angular2+ 中封装调用递归tree
子组件 given-person.html
<!--权限设置-选择员工-->
<li [class.noborder]="!dir.shierarchy" *ngFor="let dir of directories" [ngStyle]="{'margin-left': 5+(dir.shierarchy*.5)+'px'}">
<span *ngIf="dir.employee.length && dir[files.filename]">
<i (click)="toggle(dir)"
[ngClass]="{
'file-open': files.icon==='file' && dir.toggle,
'file-close': files.icon==='file' && !dir.toggle
}"></i>
<input (click)="onAllChecked(dir)" type="checkbox" [(ngModel)]="dir.isChecked">
<em class="filename">{{dir[files.filename]}}</em>
</span> <ng-container *ngIf="dir.toggle">
<ng-container *ngIf="dir.employee.length"> <label class="emname" [ngStyle]="{'margin-left': 5+(dir.shierarchy*.5)+'px'}" *ngFor="let em of dir.employee">
<!-- 当部门选中之后,下面的员工都被选中,并禁用掉不让取消勾选 -->
<input (click)="callback(em)" type="checkbox" [(ngModel)]="em.isChecked" [disabled]="dir.isChecked">
{{em.emName}}</label>
</ng-container>
<ng-container *ngIf="dir[files.child]">
<app-given-person [directories]="dir[files.child]" [files]='files' (callbackEvent)="files.callback($event,files.that)"></app-given-person> </ng-container>
</ng-container>
</li>
子组件 given-person.ts
import {Component, OnInit, Input, Output, EventEmitter, OnChanges} from '@angular/core'; @Component({
selector: 'app-given-person',
templateUrl: './given-person.component.html',
styleUrls: ['./given-person.component.scss']
})
export class GivenPersonComponent implements OnChanges, OnInit {
@Input() directories;
@Input() files;
@Output() callbackEvent = new EventEmitter(); constructor() {
} ngOnInit() { } ngOnChanges() {
this.setOrganizsTree(this.directories, 0);
console.log(this.directories)
console.log(this.files)
} // 设置层级
setOrganizsTree(data, shierarchy) {
data.forEach(item => {
if (!item.isChecked) {
item.isChecked = false;
}
if (!item.shierarchy) {
item.shierarchy = shierarchy;
}
if (!item.toggle) {
item.toggle = true;
}
if (item.departs.length !== 0) {
console.log(item.shierarchy);
const shierarchy1 = item.shierarchy + 1;
this.setOrganizsTree(item.departs, shierarchy1); // 递归
}
});
} toggle(dir) {
dir.toggle = !dir.toggle;
} callback(dir) {
// console.log(dir)
this.callbackEvent.emit(dir);
} // 全选
onAllChecked(dir) {
dir.touch = 'touch';
this.callbackEvent.emit(dir);
this.checkedAll(dir, !dir.isChecked); }
// 全选
checkedAll(dir, bools) {
// 点击部门把部门下的所有人选中
if (dir.departs && dir.departs.length !== 0) {
dir.departs.forEach(item => {
item.isChecked = bools;
});
dir.departs.forEach(item => {
this.checkedAll(item, bools);
item.touch = 'no';
});
} if (dir.employee && dir.employee.length !== 0) {
dir.employee.forEach(item => {
item.isChecked = bools;
});
dir.employee.forEach(item => {
this.checkedAll(item, bools);
item.touch = 'no';
});
} } }
页面中调用 demo.component.ts
<button (click)="showAddSuperAdmin=true"></button> <!-- 选择发送对象,部门或个人,选择部门时意味着选的是部门下所有人 -->
<div class="mask" *ngIf="showAddSuperAdmin">
<div class="alert-content">
<div class="title">选择发送对象<span class="close-btn" (click)="showAddSuperAdmin=false">×</span></div>
<div class="container clearFix">
<div class="pull-left">
<div class="tit">选择:</div>
<div class="structure">
<form [formGroup]="departsForm" class="search" *ngIf="departsForm">
<input type="text" placeholder="搜索" formControlName="departsNameSearch">
<span class="sear-close" *ngIf="departsForm.get('departsNameSearch').value" (click)="searchTreeClose()">×</span>
<img src="../assets/icon/ser.png">
</form>
<i style="opacity: 0;height: 1px;overflow: hidden;width:1px;display: inline-block">{{filteredStates | async}}</i>
<!-- <orangize-tree [treelist]="menu"></orangize-tree> -->
<div class="organiz">
<label class="all" *ngIf="departsFormResult.show"><input type="checkbox" [(ngModel)]="allCheckOrganizsEmployee" (change)="allCheckOrganizsEmployeeEvent()"> 全选 </label>
<app-given-person *ngIf="departsFormResult.show" [directories]="organizsTreeOriginal" (callbackEvent)="callbackEvent($event,this)" [files]="filesTree"></app-given-person>
<div *ngIf="organizsFilterStaff.length===0">{{departsFormResult.msg}}</div>
<ng-container *ngIf="!departsFormResult.show">
<label class="emname" *ngFor="let em of organizsFilterStaff"><input [disabled]="allCheckOrganizsEmployee" (click)="callbackEvent(em,this)" type="checkbox" [(ngModel)]="em.isChecked">{{em.emName}}------{{em.parent}}</label>
</ng-container>
</div>
</div>
</div>
</div>
<div class="btn-wrap"><button class="btn bgblue submit" (click)="onSave()">确定</button></div>
</div>
</div>
ts
showAddSuperAdmin = false;
departsForm: FormGroup; // 部门搜索
departsFormResult = {show: false, msg: '查询中...'};
filteredStates: Observable<string>;
organizsTreeOriginal = []; // 左侧树结构原始数据
organizsFilterStaff = []; // 模糊查询显示员工
selectedStaffs = [];
filesTree = {
'titleshow': false,
'child': 'departs',
'filename': 'departmentName',
'icon': 'file',
'callback': null, // 在初始函数里面讲callback初始化 this.filesTree.callback = this.callbackEvent;
'that': this
}; ngOnInit() {
this.filesTree.callback = this.callbackEvent;
} selectedDeparts = []; // 部门或人
onSave(){ // 保存发送对象
this.showAddSuperAdmin = false;
this.selectedDeparts = [];
this._addGiven(this.organizsTreeOriginal);
console.log(this.selectedDeparts)
this.params.sendTarget = this.selectedDeparts;
const arr = [];
this.params.sendTarget.forEach(i=>{
arr.push(i.sendName)
})
this.addsendName = arr.join(',') } // 在给后台传参的时候,如果是选择部门就只传部门,相当于会发给部门下所有人,如果是选择的是部门下面的某个或某几个人,就传这几个人和和对应的id,selectedDeparts是要传给后台的参数
_addGiven(data) {
data.forEach(item => {
if (item.isChecked) { const option = {sendName:item.departmentName, sendEmId:''}
this.selectedDeparts.push(option);
}
if (item.departs.length !== 0 && !item.isChecked) {
this._addGiven(item.departs);
}
if (item.employee.length !== 0&& !item.isChecked) { this._addEmployee(item.employee);
}
});
} _addEmployee(data){
data.forEach(item=>{
if(item.isChecked){
const option = {sendName:item.emName, sendEmId:item.emId}
this.selectedDeparts.push(option)
}
})
} private allCheckOrganizsEmployee = false;
allCheckOrganizsEmployeeEvent() {
this._allCheckOrganizsEmployee(this.organizsTreeOriginal, this.allCheckOrganizsEmployee)
} _allCheckOrganizsEmployee(data, b) {
data.forEach(item => {
item.isChecked = b;
if (item.employee !== 0) { // 如果有员工
item.employee.forEach(em => {
em.isChecked = b;
});
}
if (item.departs.length !== 0) { // 如果还有部门
this._allCheckOrganizsEmployee(item.departs, b)
}
})
} // 点击叉叉清空value;
searchTreeClose (){
this.departsForm.patchValue({departsNameSearch: ''});
}
// 订阅搜索部门
departsNameSearchInit() {
this.departsForm = this.fb.group({
departsNameSearch: ['']
})
this.filteredStates = this.departsForm.get('departsNameSearch').valueChanges.pipe(
startWith(''),
debounceTime(300),
map(state => {
// // console.log(state)
if (state === '') {
this.departsFormResult.show = true;
} else {
this.departsFormResult.show = false;
}
this.organizsFilterStaff = [];
this.setPageOrganizsTree(state, this.organizsTreeOriginal) if (this.organizsFilterStaff.length === 0) {
this.departsFormResult.msg = `没有查询到 "${state}"`;
}
return state;
})
);
} // 选择发送对象
selectedStaffsEvent(data, type, user?) {
data.forEach(item => {
if (item.employee !== 0) { // 如果有员工
item.employee.forEach(em => {
if (em.isChecked) {
this.selectedStaffs.push(em);
}
});
}
if (item.departs.length !== 0) { // 如果还有部门
if (type === 'select' || type === 'reset') { // 选择 或者重置
this.selectedStaffsEvent(item.departs, type); // 递归
}
if (type === 'delete') { // 移除
this.selectedStaffsEvent(item.departs, type, user); // 递归
} }
});
} // 筛选层级
setPageOrganizsTree(key, data) {
for (let i = 0; i < data.length; i++) {
const item = data[i];
// 如果有员工
if (item.employee.length !== 0) {
for (let j = 0; j < item.employee.length; j++) {
const staff = item.employee[j];
if (staff.emName.indexOf(key) !== -1) {// 匹配到
staff.parent = item.departmentName
this.organizsFilterStaff.push(staff);
// break;
}
}
}
// 如果有部门
if (item.departs.length !== 0) {
this.setPageOrganizsTree(key, item.departs);
}
}
} // tree callback;
callbackEvent(v, that) {
console.log(v) that.selectedStaffs = [];
setTimeout(() => {
that.selectedStaffsEvent(that.organizsTreeOriginal, 'select');
}, 0); }
angular2+ 中封装调用递归tree的更多相关文章
- 144.Binary Tree Preorder Traversal---二叉树先序、中序非递归遍历
题目链接 题目大意:返回二叉树的先序遍历list.中序见94,后序见145. 法一:普通递归遍历,只是这里多了一个list数组,所以分成了两个函数.代码如下(耗时1ms): public List&l ...
- MVC代码中如何调用api接口
关于代码解释,为了方便读者浏览时更好理解代码的含义,我把注释都写在代码里面了.因为一开始我只考虑到功能上的实现并没有考虑代码的优化所以代码我就全写在一个页面了.至于那些生成扑克牌类.计算类等代码优化方 ...
- C代码中如何调用C++ C++中如何调用C
注意这里的C调用C++或者C++调用C意思是.c文件中调用.cpp文件中代码,或者相反. 集成开发环境如VC++6.0或者vs都是以文件后缀来区别当前要编译的是C代码还是C++代码,然后采用响应的编译 ...
- 详解Webwork中Action 调用的方法
详解Webwork中Action 调用的方法 从三方面介绍webwork action调用相关知识: 1.Webwork 获取和包装 web 参数 2.这部分框架类关系 3.DefaultAction ...
- 项目开发中封装一个BarButtonItem类别-很实用
Encapsulates a TabBarItem--封装一个BarButtonItem类 在我们程序的导航栏的左边或右边一般都会有这样的BarButtonItem,用来界面之间的跳转 如果我们有很多 ...
- QT中QProcess调用命令行的痛苦经历(调用Winrar,设置工作目录,获得输出,注意引号与括号,等等)
QT中QProcess调用命令行的痛苦经历 阅读目录 创建压缩包的方法 在QT中调用命令行 在QT中调用C++创建的dll 在QT程序中需要将某些目录和文件压缩为一个rar的压缩包,于是想到了在Q ...
- 在DLL动态链接库中封装VCL的MDI子窗体
在DLL动态链接库中封装VCL的MDI子窗体不多说了,看代码就应该明白了,曾经我遇到的问题,现在放出来大家共享! 这里是工程文件的部分: 在DLL中封装MDI子窗体需要重写DLL入口函数,具体代码如下 ...
- 在C++中反射调用.NET(二)
反射调用返回复杂对象的.NET方法 定义数据接口 上一篇在C++中反射调用.NET(一)中,我们简单的介绍了如何使用C++/CLI并且初步使用了反射调用.NET程序集的简单方法,今天我们看看如何在C+ ...
- 在C++中反射调用.NET(一)
为什么要在C++中调用.NET 一般情况下,我们常常会在.NET程序中调用C/C++的程序,使用P/Invoke方式进行调用,在编写代码代码的时候,首先要导入DLL文件,然后在根据C/C++的头文件编 ...
随机推荐
- [na]华为acl(traffic-filter)和dhcp管理
这个是财务网络的一个问题, 要求财务的某台机器能访问其他部门区的打印机. 其他部门是不能访问到财务网络的. 华为alc配置实例:-traffic-filter # 在VLAN100上配置基于ACL的报 ...
- android线程控制UI更新(Handler 、post()、postDelayed()、postAtTime)
依照以下的理解就是handler与ui线程有一定的关联能够由于更新界面仅仅能在主线程中全部更新界面的地方能够在接受消息的handleMessage那里还有更新界面能够在handler.port(new ...
- java中Keytool的使用总结 (加密 密钥(key)和证书(certificates))
http://blog.chinaunix.net/uid-17102734-id-2830223.html
- 基于jQuery左侧小图滚动右侧大图显示代码
今天给大家分享一款 jQuery左侧小图滚动右侧大图显示代码是一款基于jQuery实现的左侧滚动图片点击大图查看效果代码.该实例适用浏览器:IE8.360.FireFox.Chrome.Safari. ...
- Odoo ParseError:"decoder jpeg not available" while parsing....
The reason causing this problem is the plugin PIL install error to solve this problem,try this: 1. c ...
- [ucos]了解ucos
1. uCosIII移植到STM32F10x http://www.cnblogs.com/hiker-blogs/archive/2012/06/13/2547176.html 2. uCosIII ...
- 一次完整的https过程
参考: 1. 一次完整的HTTP事务是怎样一个过程? 2. The First Few Milliseconds of an HTTPS Connection 3. 也许,这样理解HTTPS更容易 4 ...
- phpadmin 装了6666端口只能在IE打开,在阿里云改了 开放端口85好了
phpadmin 装了6666端口只能在IE打开,在阿里云改了 开放端口85好了 非常用端口谷歌浏览器识别不了phpadmin
- KMP算法完整教程 (下)
下面我们用数学归纳法来解决这个填值的问题. 这里我们借鉴数学归纳法的三个步骤(或者说是动态规划?): 1.初始状态 2.假设第j位以及第j位之前的我们都填完了 3.推论第j+1位该怎么填 初始状态我们 ...
- java 包 和 物理目录 解惑
今天做 JUnit 实验, 发现在物理实际不同的目录(src, testsrc)下可以使用相同的包名, 并且在这两个目录下, 都有个子目录 coolUnit (这个子目录是配合 package 使用的 ...