angulr7 結合 material UI 權限樹

由於在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 = “”;
}
}
}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章