由于在angular中引入了material UI 又不想引入zTree。所以就自己写了个checkbox的权限树;
写得不好的地方请大家多多指教。项目中还有其它方法,直接拷贝了。多余的可自行删除:
注:记得在app.module.ts中引入material相关组件;
import:中的没有自行删除
JavaScript代码:
import {CdkTreeModule} from '@angular/cdk/tree'; //树
import {
MatGridListModule,
MatInputModule,
MatAutocompleteModule,
MatButtonModule,
MatButtonToggleModule,
MatCardModule,
MatCheckboxModule,
MatChipsModule,
MatDatepickerModule,
MatDialogModule,
MatExpansionModule,
MatIconModule,
MatListModule,
MatMenuModule,
MatNativeDateModule,
MatPaginatorModule,
MatProgressBarModule,
MatProgressSpinnerModule,
MatRadioModule,
MatRippleModule,
MatSelectModule,
MatSidenavModule,
MatSliderModule,
MatSlideToggleModule,
MatSnackBarModule,
MatSortModule,
MatTableModule,
MatTabsModule,
MatToolbarModule,
MatTooltipModule,
MatStepperModule,
MatFormFieldModule,
} from '@angular/material';
@NgModule({
imports: [
BrowserModule,
FormsModule,
AppRoutingModule,
ReactiveFormsModule,
MatGridListModule,
MatInputModule,
MatAutocompleteModule,
MatButtonModule,
MatButtonToggleModule,
MatCardModule,
MatCheckboxModule,
MatChipsModule,
MatDatepickerModule,
MatDialogModule,
MatExpansionModule,
MatIconModule,
MatListModule,
MatMenuModule,
MatNativeDateModule,
MatPaginatorModule,
MatProgressBarModule,
MatProgressSpinnerModule,
MatRadioModule,
MatRippleModule,
MatSelectModule,
MatSidenavModule,
MatSliderModule,
MatSlideToggleModule,
MatSnackBarModule,
MatSortModule,
MatTableModule,
MatTabsModule,
MatToolbarModule,
MatTooltipModule,
MatStepperModule,
MatFormFieldModule,
BrowserAnimationsModule,
SwiperModule,
HttpClientModule,
HttpClientJsonpModule,
FunctionModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (createTranslateHttpLoader),
deps: [HttpClient]
}
}),
OverlayModule,
CdkTreeModule
],
})
common.ts:
JavaScript代码
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material';
import { isArray } from 'util';
/**
*一个公共类库
*
* @export
* @class CommonService
*/
@Injectable({
providedIn: 'root'
})
export class CommonService {
constructor(public snackBar: MatSnackBar) { }
/**
* checkBox选取所有
* 参数说明:
* @param checkBtn:选项按钮的dom
* @param checkList:子项的dom数组;
*/
getCheckAll(checkBtn, checkList: Array<any>) {
if (!checkBtn || !checkList) {
return;
}
if (checkBtn.checked) {
for (let dom of checkList) {
dom.checked = true;
}
} else {
for (let dom of checkList) {
dom.checked = false;
}
}
}
/**
* 获取checkBox的所有数据
* 参数说明
* @param dom 子项的dom数组
* @returns 返回值数组
*/
getCheckData(dom: Array<any>) {
if (!dom) {
return;
}
let datas = [];
for (let d of dom) {
if (d.checked) {
if (d.value)
datas.push(d.value);
}
}
return datas;
}
/**
*checkbox全选或取消事件
*参数说明
* @param {*} domList 子项的dom数组
* @param {*} checkedDom 全选按钮dom
* @memberof CommonService
*/
checkboxFlag(domList, checkedDom) {
for (let i = 0; i < domList.length; i++) {
if (domList[i].checked) {
checkedDom.checked = true;
} else {
checkedDom.checked = false;
break;
}
}
}
/**
*获取下拉列表选中的值
*参数说明
* @param {Array<any>} dom option对象数组
* @returns
* @memberof CommonService
*/
getSelect(dom: Array<any>) {
let val;
dom.forEach(element => {
if (element.selected == true) {
val = element.value;
}
});
return val;
}
/**
*根据子key返回为对象的父级key数组
*参数说明
* @param {*} json json对象
* @param {*} key
* @returns 返回值为对象的父级key数组
* @memberof CommonService
*/
getParentKey(json, key: string) {
let tem = [];
let results = [];
let keys = Object.keys(json);
(function argument(json) {
for (let k of Object.keys(json)) {
if (keys.indexOf(k) >= 0) { //每次回调到顶级父元素时
tem = [];
}
if (typeof json[k] === "object") { //回调的条件
tem.push(k); //该key的值为对象时保存
argument(json[k]);
}
if (k === key) {
results = results.concat(tem);
}
}
})(json);
let res = [];
for (let i = 0; i < results.length; i++) {
if (this.getAllKey(json, results[i]).indexOf(key) < 0) {
continue;
}
res.push(results[i]);
}
return res;
}
/**
*根据父级key获取所有的子key
*参数说明
* @param {*} json
* @param {*} pKey
* @returns 返回子key数组
* @memberof CommonService
*/
getAllKey(json, pKey) {
let results = [];
(function argument1 (json) {
for (let k of Object.keys(json)) {
if (typeof json[k] === "object") { //回调的条件
argument1(json[k]);
}
if (k === pKey) {
(function argument2 (subJson) {
for (let j of Object.keys(subJson)) {
if (typeof subJson[j] === "object") { //回调的条件
results.push(j);
argument2(subJson[j]);
}else{
results.push(j); //该key的值为非对象时保存
}
}
})(json[k]);
}
}
})(json);
return results;
}
/**
*根据父级key获取所有非对象的子key
*参数说明
* @param {*} json
* @param {*} pKey
* @returns 非对象子key数组
* @memberof CommonService
*/
getSubKey(json, pKey: string) {
let results = [];
(function argument1(json) {
for (let k of Object.keys(json)) {
if (typeof json[k] === "object") { //回调的条件
argument1(json[k]);
}
if (k === pKey) {
(function argument2(subJson) {
for (let j of Object.keys(subJson)) {
if (typeof subJson[j] === "object") { //回调的条件
argument2(subJson[j]);
} else {
results.push(j); //该key的值为非对象时保存
}
}
})(json[k]);
}
}
})(json);
return results;
}
}
html:
XML/HTML代码
权限列表
css:
XML/HTML代码
.jurisdiction_list {
flex: 3.2;
width: 100%;
height: 100%;
text-align: center;
overflow: hidden;
>h1 {
font-size: 20px;
padding: 8px;
border-bottom: solid 1px $borderColor;
}
}
.jurisdiction_list {
color: #fff;
.j_list {
width: 100%;
height: 89.5%;
text-align: left;
padding: 10px 0 0 10px;
border-left: solid 1px $borderColor;
>div:nth-child(1) {
border-bottom: solid 1px $vivoColor;
margin-bottom: 15px;
}
>div:nth-child(2) {
height: 93%;
overflow: auto;
position: relative;
left: -15px;
}
.check:after{
content: “”;
color: transparent;
display: block;
position: absolute;
width: 10px;
height: 10px;
background-color: #5fb75f;
border: solid 1px #aaa;
border-radius: 3px;
}
}
.example-tree-invisible {
display: none;
}
.example-tree ul,
.example-tree li {
margin-top: 0;
margin-bottom: 0;
list-style-type: none;
margin: 0;
padding: 0;
}
.example-tree-node {
display: block;
padding-left: 15px;
.mat-icon-button{
height: 24px;
line-height: 24px;
}
}
}
}
ts:
XML/HTML代码
import { Component, OnInit, ElementRef, Renderer2 } from ‘@angular/core’;
import { CommonService } from ‘…/…/…/service/common/common.service’;
import { Router, ActivatedRoute } from ‘@angular/router’;
import { MatSnackBar } from ‘@angular/material’;
import { Title } from ‘@angular/platform-browser’;
//树
import { NestedTreeControl } from ‘@angular/cdk/tree’;
import { Injectable } from ‘@angular/core’;
import { MatTreeNestedDataSource } from ‘@angular/material/tree’;
import { BehaviorSubject, of as observableOf } from ‘rxjs’;
//树
/**
- Json node data with nested structure. Each node has a filename and a value or a list of children
*/
export class FileNode {
children: FileNode[];
filename: string;
type: any;
}
/**
- File database, it can build a tree structured Json object from string.
- Each node in Json object represents a file or a directory. For a file, it has filename and type.
- For a directory, it has filename and children (a list of files or directories).
- The input will be a json object string, and the output is a list of
FileNode
with nested - structure.
*/
@Injectable()
export class FileDatabase {
dataChange = new BehaviorSubject<FileNode[]>([]);
get data(): FileNode[] { return this.dataChange.value; }
public dataObject;
constructor() {
this.initialize();
}
initialize() {
//在这从后台获取数据
// Parse the string to json object.
//注意json中key的命名不要与id选择器相冲突就行
this.dataObject = {
“other”: {
“other-1”: “/superuser”,
“other-2”: “home/function/superuser”,
“other-3”: “home/function”,
},
“test”:{
“test1”:{
“test2”:{
“test2-1”: “home/function/deviceManagement/facilityMain/facilityMain”,
“test2-2”: “home/function/deviceManagement/plantDetail”,
“other2”: {
“other2-1”: “/superuser”,
“other2-2”: “home/function/superuser”,
“other2-3”: “home/function”,
},
},
“zhuangpei”: {
“zhuangpei-1”: “home/function/fabricationMES/exhibitionHall”,
“zhuangpei-2”: “home/function/fabricationMES/equipmentData”,
},
}
}
}
// Build the tree nodes from Json object. The result is a list of `FileNode` with nested
// file node as children.
const data = this.buildFileTree(this.dataObject, 0);
// Notify the change.
this.dataChange.next(data);
}
/**
-
Build the file structure tree. The
value
is the Json object, or a sub-tree of a Json object. -
The return value is the list of
FileNode
.
*/
buildFileTree(obj: { [key: string]: any }, level: number): FileNode[] {
return Object.keys(obj).reduce<FileNode[]>((accumulator, key) => {
const value = obj[key];
const node = new FileNode();
node.filename = key;if (value != null) {
if (typeof value === ‘object’) {
node.children = this.buildFileTree(value, level + 1);
} else {
node.type = value;
}
}
return accumulator.concat(node);
}, []);
}
}
@Component({
selector: ‘app-super-user’,
templateUrl: ‘./super-user.component.html’,
styleUrls: [’./super-user.component.scss’],
providers: [FileDatabase] //树添加的
})
export class SuperUserComponent implements OnInit {
//树
nestedTreeControl: NestedTreeControl;
nestedDataSource: MatTreeNestedDataSource;
hasNestedChild = (_: number, nodeData: FileNode) => !nodeData.type;
private _getChildren = (node: FileNode) => observableOf(node.children);
constructor(private el: ElementRef,
private ren: Renderer2,
private common: CommonService,
private router: Router,
private database: FileDatabase) {
//标题
title.setTitle(aRoute.snapshot.data.title);
thisthis.sUserDatas = this.userDatas;
//树
this.nestedTreeControl = new NestedTreeControl<FileNode>(this._getChildren);
this.nestedDataSource = new MatTreeNestedDataSource();
database.dataChange.subscribe(data => this.nestedDataSource.data = data);
}
//权限全选/取消
jurisdictionCheckAll(id) {
let that = this;
let checkBtn = that.el.nativeElement.querySelector("#" + id);
let checkDomList = that.el.nativeElement.querySelectorAll("#JurisdictionList input");
that.common.getCheckAll(checkBtn, checkDomList);
//清除所有父级下子级不是全选的标示
(function getObj(dataObject) {
for (let key of Object.keys(dataObject)) {
if(isObject(dataObject[key])){
let d = that.el.nativeElement.querySelector("#" + key);
if (d.checked) {
d.className = “”;
}
getObj(dataObject[key]);
}
}
})(dataObject)
}
//子级全选/取消
jurisdictionCheckSubAll(id) {
let that = this;
let checkBtn = that.el.nativeElement.querySelector("#" + id);
let checkDomList = that.el.nativeElement.querySelectorAll("#"+id+"~div input");
that.common.getCheckAll(checkBtn, checkDomList);
}
//添加权限
addJurisdiction() {
let that = this;
let JCheckDomList = that.el.nativeElement.querySelectorAll("#JurisdictionList input");
let jDatas = that.common.getCheckData(JCheckDomList); //权限
console.log(jDatas);
}
//全选/不选关联事件
checkboxFun(allId, id) {
let that = this;
let dom = this.el.nativeElement.querySelectorAll("#" + allId + " input");
that.common.checkboxFlag(dom, that.el.nativeElement.querySelector("#" + id));
}
checkboxSubFun(subId, allId, id) {
let that = this;
let pIds = that.common.getParentKey(that.database.dataObject, subId);
let subKeys = that.common.getSubKey(that.database.dataObject, pIds[0]); //pIds[0]顶级父key
let pIdDoms = [];
for (let key of subKeys) { //获取所有子级的父级key
pIdDoms.push(that.el.nativeElement.querySelector("#" + key));
}
for (let pid of pIds) {
that.common.checkboxFlag(pIdDoms, that.el.nativeElement.querySelector("#" + pid));
that.getActiveSubParentKey(pid, that.database.dataObject);
}
that.getActiveAddParentKey(pIds, that.database.dataObject);
that.checkedFlagFun(pIds);
that.checkboxFun(allId, id);
}
//已知父级key 获取所有父级key下的所有子key,判断父级key是否添加标示
getActiveAddParentKey(pids, json) {
let that = this;
let checkFlag = true;
for (let j = pids.length - 1; j >= 0; j–) {
let subId = this.getParentReturnSubKey(json, pids[j]);
console.log(“pid:” + pids[j]);
for (let i = 0; i < subId.length; i++) {
if (!that.el.nativeElement.querySelector("#" + subId[i]).checked) {
checkFlag = false;
break;
}
}
if (checkFlag) {
that.el.nativeElement.querySelector("#" + pids[j]).checked = true;
}
}
}
//点击当前去除上级key
getActiveSubParentKey(pid, json) {
let that = this;
let subId = this.getParentReturnSubKey(json, pid);
for (let id of subId) {
if (that.el.nativeElement.querySelector("#" + id).checked) {
that.el.nativeElement.querySelector("#" + pid).checked = true;
} else {
that.el.nativeElement.querySelector("#" + pid).checked = false;
break;
}
}
}
//根据上级key返回所有下级的key
getParentReturnSubKey(json, pKey: string) {
let results = [];
(function argument1(json) {
for (let k of Object.keys(json)) {
if (typeof json[k] === “object”) { //回调的条件
argument1(json[k]);
}
if (k === pKey) {
(function argument2(subJson) {
for (let j of Object.keys(subJson)) {
results.push(j); //该key的值为非对象时保存
if (typeof subJson[j] === “object”) { //回调的条件
argument2(subJson[j]);
}
}
})(json[k]);
}
}
})(json);
return results; //
}
//添加已选中父级的标识
checkedFlagFun(pIds) {
let that = this;
for (let pid of pIds) {
let subKeys = that.common.getSubKey(that.database.dataObject, pid);
for (let i = 0; i < subKeys.length; i++) {
if (that.el.nativeElement.querySelector("#" + subKeys[i]).checked) {
that.el.nativeElement.querySelector("#" + pid).className = “check”;
break;
}
that.el.nativeElement.querySelector("#" + pid).className = “”;
}
if (that.el.nativeElement.querySelector("#" + pid).checked) {
that.el.nativeElement.querySelector("#" + pid).className = “”;
}
}
}
//直接点击时清除样式
clickChecked(subId, e) {
e = e || window.event;
let that = this;
let dom = e.target;
if (dom.checked) {
dom.className = “”;
}
let pIds = that.getParentReturnSubKey(that.database.dataObject, subId)
for (let res of pIds) {
let d = that.el.nativeElement.querySelector("#" + res);
if (d.checked) {
d.className = “”;
}
}
}
}