一、步骤
一、安装JQuery
npm install --save jquery
npm install --save @types/jquery
二、安装ztree/ztree_v3
npm install --save @ztree/ztree_v3
三、angular.json配置
"styles": [
......
"node_modules/@ztree/ztree_v3/css/zTreeStyle/zTreeStyle.css"
],
"scripts": [
......
"node_modules/jquery/dist/jquery.min.js",
"node_modules/@ztree/ztree_v3/js/jquery.ztree.all.js"
]
四、在组件中声明$,初始化
html
<ul id="ztree" class="ztree"></ul>
ts
declare var $: any;
@Component({
selector: 'app-root',
template: `<ul id="ztree" class="ztree"></ul>`,
})
export class AppComponent implements OnInit {
zTreeObj;
// zTree 的参数配置,深入使用请参考 API 文档(setting 配置详解)
setting = {};
// zTree 的数据属性,深入使用请参考 API 文档(zTreeNode 节点数据详解)
zNodes = [
{name:"test1", open:true, children:[
{name:"test1_1"}, {name:"test1_2"}]},
{name:"test2", open:true, children:[
{name:"test2_1"}, {name:"test2_2"}]}
];
ngOnInit(){
this.zTreeObj=$.fn.zTree.init($("#ztree"), this.setting, this.zNodes);
}
}
二、使用问题
demo中模糊搜索fuzzySearch()方法中exhide()不存在
hideNode()方法位于jquery.ztree.exhide.js中
angular.json配置
"scripts": [
......
"node_modules/@ztree/ztree_v3/js/jquery.ztree.exhide.js"
]
三 :方法介绍
html:
<ul [id]="ztree" class="ztree" [style]="styles">
</ul>
ts:
@ViewChild('tree') treeComponent: TreeComponent;
// 请求url
@Input() requestUrl = environment.INTERFACE_URL + '/api/getTreeData';
/**
* 请求body
* body={treeType: string,assetType: string,showPrivilege:boolean}
* treeType(树类型): 部门树:"group",高速路树:"highway",菜单树:"privilege",辖区树:"belongarea"
* assetType(设备类型):'1':卡口,'2':监控,'3':广播,'4':诱导屏,'5':气象
* showPrivilege(数据权限):true,false
*/
ztree
@Input() requestBody;
// 请求params
@Input() requestParams;
@Input() beforeSend;
// 请求成功后回调函数
@Input() onQuerySuccess: (data: any) => any;
// 是否显示复选框
@Input() showCheckbox: boolean = false;
// 是否显示搜索框
@Input() showSearch: boolean = true;
// 是否显示虚拟滚动
@Input() virtualScroll: boolean = false;
@Input() nodes = [];
@Input() actionMapping: IActionMapping = {
mouse: {
click: (tree, node, $event) => {
TREE_ACTIONS.ACTIVATE(tree, node, $event);
this.activatedNode = node;
this.onClick.emit(node);
},
contextMenu: (tree, node, $event) => {
TREE_ACTIONS.ACTIVATE(tree, node, $event);
this.onContextMenu.emit({ node, $event });
},
dblClick: (tree, node, $event) => {
TREE_ACTIONS.TOGGLE_EXPANDED(tree, node, $event);
this.onDblClick.emit(node);
},
},
};
@Input() options: ITreeOptions = {
displayField: 'NAME',
idField: 'ID',
isExpandedField: 'expand',
actionMapping: this.actionMapping,
};
// ztree 配置
@Input() setting;
// 勾选
@Output() onCheck = new EventEmitter<any>();
// 根节点
@Output() sendNodes = new EventEmitter<any>();
// 单击
@Output() onClick = new EventEmitter<any>();
// 双击
@Output() onDblClick = new EventEmitter<any>();
// 右击
@Output() onContextMenu = new EventEmitter<any>();
@Input() setStyles
activatedNode;
groupName = '';
searchParam: string = '';
data: any;
//ztree
nameKey = 'NAME';
idKey = 'ID';
pIdKey = 'PID';
zTreeObj;
//树样式格式
//[setStyles]="{'max-height': '97%','overflow':'auto'}"
styles={'max-height': 'calc(100vh - 450px)','overflow':'auto'};
ngOnInit() {
//解决同一页面多棵树id冲突问题
this.ztree="ztree"+new Date().getTime();
if(!isNullOrUndefined(this.setStyles)){
this.styles=this.setStyles;
}
if(this.virtualScroll){
this.options.useVirtualScroll = true;
this.options.nodeHeight = 22;
}
this.setting = this.setting || this.initSetting();
this.onQuerySuccess = this.onQuerySuccess || this.querySuccess;
this.queryNodes();
}
queryNodes() {
this.getTreeData(this.requestUrl, this.requestBody, this.requestParams, this.beforeSend, this.onQuerySuccess);
}
getTreeData(url, body, params, beforeSend, onQuerySuccess) {
this.http.post(url, body, params).subscribe(
(data: any) => {
if (onQuerySuccess) onQuerySuccess(data)
});
}
datas:any;
querySuccess = (data) => {
this.datas = this.showIcon(data);
this.zTreeObj = $.fn.zTree.init( $("#"+this.ztree), this.setting, this.datas);
this.initFuzzySearch(null,false);
$("#"+this.ztree).css(this.styles);
}
ngAfterViewInit() {
}
/**
* 刷新树
*/
nflag:boolean=true;
treeRefresh(){
if(this.nflag){
this.zTreeObj.destroy();
this.zTreeObj = $.fn.zTree.init($("#"+this.ztree), this.setting, this.datas);
// this.zTreeObj = $.fn.zTree.init($("#ztree"), this.setting, this.datas);
$("#"+this.ztree).css(this.styles);
}
this.nflag=false;
}
/**
* 图标
* @param element
*/
showIcon(element) {
let icon = '';
element.forEach(data => {
if(isNullOrUndefined(data.PID)||data.PID=="null"||data.PID=="0"){
data.open=true;
}else{
data.open=false;
}
// 部门
if (data.ICON === "depart") {
icon = 't.png';
// 高速
} else if (data.ICON === "highway") {
icon = 'm.png';
// 菜单
} else if (data.ICON === "privilege") {
icon = 't.png';
// 设备
} else if (data.ICON === "police") {
icon = 'police.png';
} else if (data.ICON === "car") {
icon = 'car1.png';
} else if (data.ICON === "asset") {
// 监控
if (data.ASSET_TYPE === '2') {
// 1:在线,0:离线
if (data.STATUS === 1) {
icon = 'icon_camera_on.png';
} else {
icon = 'icon_camera_off.png';
}
// 诱导屏
} else if (data.ASSET_TYPE === '4') {
// 1:在线,0:离线
if (data.STATUS === 1) {
icon = 'tree_icon_ydp_on.png';
} else {
icon = 'tree_icon_ydp_off.png';
}
// 卡口
} else if (data.ASSET_TYPE === '1') {
// 1:在线,0:离线
if (data.STATUS === 1) {
icon = 'tree_icon_ko_on.png';
} else {
icon = 'tree_icon_ko_off.png';
}
} else {
icon = 't.png';
}
} else {
icon = 't.png';
}
data.icon='/assets/images/'+icon
});
return element;
}
/**
* 获取选中的节点 ztree
*/
public getSelectedNode() {
return this.activatedNode;
}
/**
* 获取选中的节点的属性值,默认获取ID属性值
* @param idField 属性名,默认ID ztree
*/
public getSelectedNodeId(idField = 'ID') {
const node =this.getSelectedNode();
return node.data[idField];
}
/**
* 根据一组子节点id勾选子节点,自动遍历勾选父节点
* @param ids 节点id列表 ztree
*/
public setCheckedNodesByChildIds(ids) {
this.clearTree();
ids.forEach(id => this.setCheckedNodeByChildId(id, true));
}
/**
* 根据子节点id勾选子节点,自动遍历勾选父节点
* @param id 节点的id
* @param checked 是否勾选 ztree
*/
public setCheckedNodeByChildId(id, checked) {
const node = this.getNodeById(id);
if (node && node.data) {
this.check(node, checked);
}
}
/**
* 获取勾选中的子节点,需要初始化时获取所有节点 ztree
*/
getCheckedChildNodes() {
const nodeArray = new Array();
let treeNodeArray = this.zTreeObj.transformToArray(this.zTreeObj.getNodes());
if (treeNodeArray.length > 0) {
treeNodeArray.forEach(node => {
if(!node.isParent){
if(node.checked){
nodeArray.push(node);
}
}
});
}
return nodeArray;
}
/**
* 根据一组id勾选节点
* @param ids 节点id列表 ztree
*/
public setCheckedNodesByIds(ids) {
// this.clearTree();
let treeNode = this.zTreeObj.getNodes();
ids.forEach(id => this.setCheckedNodeById(id,treeNode, true));
}
/**
* 根据id勾选节点
* @param id 节点的id
* @param checked 是否勾选 ztree
*/
public setCheckedNodeById(id, treeNode,checked) {
treeNode.forEach(element => {
if(element.isParent){
this.setCheckedNodeById(id,element.children,checked);
}else{
if(element.ID==id){
element.checked=true;
this.zTreeObj.checkNode(element,true,true);
}
}
});
// console.log(treeNode);
}
//先更新父子节点的check状态 然后子组件自定义的事件onCheck触发,执行父组件的onCheck方法 ztree
public check(node, checked) {
;
this.zTreeObj.checkNode(node,checked,true);
}
/**
* 获取勾选中的节点的id,需要初始化时获取所有节点
* @param idField id的属性名,默认值ID
*/
public getCheckedNodeIds(idField = 'ID') {
let ids = [];
const nodes = this.getCheckedNodes();
nodes.forEach(node => ids.push(node[idField]));
return ids;
}
/**
* 获取勾选中的节点,需要初始化时获取所有节点
*/
public getCheckedNodes() {
const nodeArray = new Array();
if (this.nodes.length > 0) {
this.nodes.forEach(node => {
this.getCheckedNodeKeyId(node, nodeArray);
});
}
return nodeArray;
}
/**
* 循环遍历勾选中的节点
* @param node 树的节点集合
* @param nodeArray 符合条件的结果集合
*/
public getCheckedNodeKeyId(node, nodeArray) {
if (node.checked) {
nodeArray.push(node);
}
if (node.children !== undefined && node.children.length > 0) {
node.children.forEach(child =>
this.getCheckedNodeKeyId(child, nodeArray),
);
}
}
/**
* 获取勾选中的子节点的单个属性集合,默认ID集合
* @param idField 属性名,默认ID ztree
*/
public getCheckedChildNodeIds(idField = 'ID') {
let ids = [];
const nodes =this.zTreeObj.getCheckedNodes(true);
nodes.forEach(node => {
if(!node.isParent){
ids.push(node[idField]);
}
});
// nodes.forEach(node => ids.push(node[idField]));
return ids;
}
/**
* 根据节点获取勾选的子节点
* @param node 树的节点集合
* @param nodeArray 符合条件的结果集合
*/
getCheckedChildNodeKeyIds(node, nodeArray) {
if (node.checked) {
if (!isNullOrUndefined(node.children) && node.children.length > 0) {
node.children.forEach(child =>
this.getCheckedChildNodeKeyIds(child, nodeArray),
);
} else {
nodeArray.push(node);
}
}
}
addNode(node, data) {
if (isNullOrUndefined(node.children)) {
node.children = [];
}
node.children.push({
NAME: data.NAME,
ID: data.ID,
PID: data.PID,
TYPE: data.TYPE,
expand: true,
});
this.treeComponent.treeModel.update();
}
/**
* 获取根节点
*/
getNodes() {
return this.nodes;
}
/**
* 根据id获取节点
* @param id 节点id ztree
*/
getNodeById(id) {
// return this.treeComponent.treeModel.getNodeById(id);
return this.zTreeObj.getNodeByParam('ID',id,null);
}
/**
* 获取节点及其子节点id
* @param node
* @param ids
*/
public getNodeIds(node, ids) {
ids.push(node.ID);
if (node.children !== undefined && node.children.length > 0) {
node.children.forEach(child => this.getNodeIds(child, ids));
}
}
/**
* 清空树的状态,勾选、选中和搜索框 ztree
*/
clearTree() {
this.zTreeObj.checkAllNodes(false);
}
// ztree 树基本配置设置
initSetting(){
let setting =
{
check: {
enable: this.showCheckbox,
},
data: {
key: {
name: this.nameKey
},
simpleData: {
enable: true,
idKey: this.idKey,
pIdKey: this.pIdKey,
rootPid: 0
}
},
view: {
showIcon: true,
showLine: false
},
callback: {
onClick: (event, treeId, treeNode, clickFlag) => this.onClick.emit({event, treeId, treeNode, clickFlag}),
onDblClick: (event, treeId, treeNode) => this.onDblClick.emit({event, treeId, treeNode}),
onRightClick: (event, treeId, treeNode) => this.onContextMenu.emit({event, treeId, treeNode}),
onCheck: (e, treeId, treeNode) => this.onCheck.emit({e, treeId, treeNode}),
}
};
return setting;
}
//ztree 树模糊查询功能
isHighLight
isExpand
rexMeta
initFuzzySearch(isHighLight, isExpand){
this.isHighLight = isHighLight===false?false:true;//default true, only use false to disable highlight
this.isExpand = isExpand?true:false; // not to expand in default
this.zTreeObj.setting.view.nameIsHTML = isHighLight; //allow use html in node name for highlight use
let metaChar = '[\\[\\]\\\\\^\\$\\.\\|\\?\\*\\+\\(\\)]'; //js meta characters
this.rexMeta = new RegExp(metaChar, 'gi');//regular expression to match meta characters
}
timeoutId = null;
keywords = '';
lastKeyword = '';
// excute lazy load once after input change, the last pending task will be cancled
searchNodeLazy(keywords) {
if (this.timeoutId) {
//clear pending task
clearTimeout(this.timeoutId);
}
this.timeoutId = setTimeout(() => {
if (this.lastKeyword === keywords) {
return;
}
this.keywords = keywords;
this.ztreeFilter(this.zTreeObj,keywords, null); //lazy load ztreeFilter function
// $(searchField).focus();//focus input field again after filtering
this.lastKeyword = keywords;
}, 500);
}
// keywords filter function
ztreeFilter(zTreeObj,_keywords,callBackFunc) {
if(!_keywords){
_keywords =''; //default blank for _keywords
}
var nodesShow = zTreeObj.getNodesByFilter(this.filterFunc.bind(this)); //get all nodes that would be shown
this.processShowNodes(nodesShow, _keywords);//nodes should be reprocessed to show correctly
}
// function to find the matching node
filterFunc(node) {
if(node && node.oldname && node.oldname.length>0){
node[this.nameKey] = node.oldname; //recover oldname of the node if exist
}
this.zTreeObj.updateNode(node); //update node to for modifications take effect
if (this.keywords.length == 0) {
//return true to show all nodes if the keyword is blank
this.zTreeObj.showNode(node);
this.zTreeObj.expandNode(node,this.isExpand);
return true;
}
//transform node name and keywords to lowercase
if (node[this.nameKey] && node[this.nameKey].toLowerCase().indexOf(this.keywords.toLowerCase())!=-1) {
this.zTreeObj.showNode(node);//show node with matching keywords
return true; //return true and show this node
}
this.zTreeObj.hideNode(node); // hide node that not matched
return false; //return false for node not matched
}
/**
* reprocess of nodes before showing
*/
processShowNodes(nodesShow,_keywords){
if(nodesShow && nodesShow.length>0){
//process the ancient nodes if _keywords is not blank
if(_keywords.length>0){
$.each(nodesShow, (n,obj) => {
var pathOfOne = obj.getPath();//get all the ancient nodes including current node
if(pathOfOne && pathOfOne.length>0){
//i < pathOfOne.length-1 process every node in path except self
for(var i=0;i<pathOfOne.length-1;i++){
this.zTreeObj.showNode(pathOfOne[i]); //show node
this.zTreeObj.expandNode(pathOfOne[i],true); //expand node
}
}
});
}else{ //show all nodes when _keywords is blank and expand the root nodes
var rootNodes = this.zTreeObj.getNodesByParam('level','0');//get all root nodes
$.each(rootNodes,(n,obj) => {
this.zTreeObj.expandNode(obj,true); //expand all root nodes
});
}
}
}