ng-zorro-antd,antd-angular树形数据动态显示操作整理及源码,各自分析拿去用吧,就是没时间整理,整体代码比较乱各位看官随意,勿喷,转载请说明出处。

import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { GlobalService } from './../../../../service/global.service';
import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
// export interface TreeNodeInterface {
//   key: number;
//   name: string;
//   age?: number;
//   level?: number;
//   expand?: boolean;
//   address?: string;
//   children?: TreeNodeInterface[];
//   parent?: TreeNodeInterface;
// }
//create by huang.l 2020.2.17 17.28
@Component({
  selector: 'app-menu',
  templateUrl: './menu.component.html',
  styleUrls: ['./menu.component.less']
})

export class MenuComponent implements OnInit {

  public pageSize: number = 15;
  public page: number = 1;
  public listOfMapData: any[];
  public mapOfExpandedData: { [key: string]: any[] } = {};
  public isVisible: boolean = false;

  public codePrefix: string = '';
  public rootId: string;
  public parentMenu: any;
  public currentArray: any[];

  validateForm: FormGroup;
  constructor(
    private globalService: GlobalService,
    private fb: FormBuilder,
  ) {

  }

  async collapse(array: any[], data: any, $event: boolean, rootId: string) {
    if ($event === false) {
      if (data.children) {
        data.children.forEach(d => {
          if (array) {
            const target = array.find(a => a.id === d.id)!;
            if (target) {//如果当前节点还存在
              target.expand = false;
              console.log(target.id);
              this.collapse(array, target, false, rootId);
            }
          }
        });
      } else {
        return;
      }
    } else {
      if (data.children) {
        return;
      }
      const submenus: any[] = await this.getChildren(data.id);
      const submenuArray: any[] = [];
      submenus.forEach(item => {
        submenuArray.push({ ...item, level: data.level + 1, expand: false, haveChild: (item.haveChild > 0 ? true : false), parent: data });
      });


      let target: any = null;
      const index = array.findIndex(item => item.id === data.id);

      target = array[index];

      if (target != null) {
        target.children = submenuArray;
      }
      //顺序调整
      // array = [...array, ...submenuArray];
      array[index] = target;
      array.splice(index + 1, 0, ...submenuArray);
      // this.mapOfExpandedData[rootId] = array;
    }

  }

  async ngOnInit() {

    this.validateForm = this.fb.group({
      id: [null],
      parentId: [null],
      parentName: [null],
      name: [null, [Validators.required, Validators.maxLength(20)]],
      code: [null, [Validators.required, Validators.maxLength(20), Validators.pattern('^[A-Za-z0-9]+$')]],
      router: [null],
      orderNum: [10, [Validators.required]],
      icon: [null],
      leaf: ['0'],
      visible: ['1'],
      openNewPage: ['0']
    });

    const menus: any[] = await this.getChildren(null);
    this.listOfMapData = menus;
    this.reload();
  }

  reload(): void {
    this.listOfMapData.forEach(item => {
      this.mapOfExpandedData[item.id] = this.convertTreeToList(item);
    });
  }


  add(): void {
    this.isVisible = true;
    this.setParentWithRoot();
  }

  convertTreeToList(root: any): any[] {
    const stack: any[] = [];
    const array: any[] = [];
    const hashMap = {};

    stack.push({ ...root, level: 0, expand: false, haveChild: (root.haveChild > 0 ? true : false) });

    while (stack.length !== 0) {
      const node = stack.pop()!;
      this.visitNode(node, hashMap, array);
      if (node.children) {
        for (let i = node.children.length - 1; i >= 0; i--) {
          stack.push({ ...node.children[i], level: node.level! + 1, expand: false, parent: node });
        }
      }
    }
    return array;
  }

  visitNode(node: any, hashMap: { [id: string]: boolean }, array: any[]): void {
    if (!hashMap[node.id]) {
      hashMap[node.id] = true;
      array.push(node);
    }
  }

  async getChildren(parentId: string) {
    let parentIdCondition: string;
    if (parentId === '' || parentId === null || parentId === undefined) {
      parentIdCondition = 'parentId=';
    } else {
      parentIdCondition = 'parentId=' + parentId;
      this.page = 1;
      this.pageSize = 9999;
    }
    const url = `api/menu/list/by/parentId?page=${this.page}&pageSize=${this.pageSize}&${parentIdCondition}`;
    try {
      const res: any = await this.globalService.axios.get(url);
      return res.data.list;
    } catch (e) {
      alert(JSON.stringify(e));
    }
  }


  async submitForm() {
    for (const i in this.validateForm.controls) {
      this.validateForm.controls[i].markAsDirty();
      this.validateForm.controls[i].updateValueAndValidity();
    }

    if (this.validateForm.valid) {

      let submitData: any = this.validateForm.getRawValue();
      submitData = { ...submitData, code: (this.codePrefix + submitData.code) };

      const res = await this.globalService.axios.post('api/menu/edit', submitData);

      if (res.data.success === true) {
        this.isVisible = false;
        this.validateForm.reset();
        //刷新表格数据
        const parentId = submitData.parentId;
        //新增根目录数据

        let editMenu: any = res.data.item;

        if (parentId === null || parentId === '' || parentId === undefined) {
          this.listOfMapData = [editMenu, ...this.listOfMapData];
          this.listOfMapData.forEach(item => {
            if (!this.mapOfExpandedData[item.id]) {
              this.mapOfExpandedData[item.id] = this.convertTreeToList(item);
            }
          });
        } else {
          //新增子目录数据
          editMenu = { ...editMenu, haveChild: false, level: (this.parentMenu.level! + 1), expand: false, parent: this.parentMenu };
          const index = this.currentArray.findIndex((item) => item.id === this.parentMenu.id);
          //设置父节点包含子节点

          //当节点未打开时,打开节点!!这句很重要
          if(!this.parentMenu.expand){
            this.parentMenu = { ...this.currentArray[index], haveChild: true, expand: true };
          }

          const chidlren: any[] = this.parentMenu['children'] ? this.parentMenu['children'] : [];
          chidlren.push(editMenu);

          this.parentMenu['children'] = chidlren;

          editMenu = { ...editMenu, parent: this.parentMenu };
          this.currentArray.splice(index + 1, 0, editMenu);
          this.currentArray[index] = this.parentMenu;
          // this.mapOfExpandedData[this.rootId] = array;
        }
        this.globalService.showSuccess();
      } else {
        this.globalService.showFail();
      }
    }
  }


  handleCancelMiddle(): any {
    this.isVisible = false;
    this.validateForm.reset();
  }

  getParent(): void {
    return;
  }

  setParentWithRoot(): void {
    this.validateForm.controls['parentId'].reset();
    this.validateForm.controls['parentName'].setValue('/');
  }

  setCode(code): void {
    this.validateForm.controls['code'].setValue(code);
  }

  addSubMenu(menu: any, array: any[], rootId: string): void {
    this.isVisible = true;
    this.validateForm.controls['parentName'].setValue(menu.name);
    this.validateForm.controls['parentId'].setValue(menu.id);
    this.codePrefix = menu.code + ':';

    this.rootId = rootId;
    this.parentMenu = menu;
    this.currentArray = array;
  }

  async deleteMenu(menu, rootId) {
    const res = await this.globalService.axios.get('api/menu/delete/' + menu.id);
    if (res.data.success === true) {
      //刷新表格
      if (menu.id === rootId) {
        delete this.mapOfExpandedData[rootId];
        //
        const rootIndex = this.listOfMapData.findIndex(item => item.id === rootId);
        this.listOfMapData.splice(rootIndex, 1);//清除列表中的数据

      } else {
        const array = this.mapOfExpandedData[rootId];
        const index = array.findIndex((item) => item.id === menu.id);
        array.splice(index, 1);

        const parentIndex: number = array.findIndex(item => item.id === menu.parentId);
        let thizParent: any = array[parentIndex];
        const parentChildrenIndex = thizParent.children.findIndex(item => item.id === menu.id);
        thizParent.children.splice(parentChildrenIndex, 1);
        if (thizParent.children.length <= 0) {//设置父节点的可删除条件
          thizParent = { ...thizParent, haveChild: false };
        }
        array[parentIndex] = thizParent;
        this.mapOfExpandedData[rootId] = array;

        //当所有子节点删完之后,更改唯一父节点的是否有子节点状态,让其变得可以删除
        // if (array.length === 1) {
        //   this.mapOfExpandedData[rootId] = [{ ...array[0], haveChild: false }];
        // }
      }
      this.globalService.showSuccess();
    } else {
      this.globalService.showFail();
    }
  }

  editMenu(menu): void {
    const menuCode: string = menu.code;
    this.codePrefix = menuCode.substr(0, menuCode.lastIndexOf(':'));
    this.isVisible = true;
    if (menu['parent']) {
      this.validateForm.controls['parentName'].setValue(menu.parent.name);
      this.validateForm.controls['parentId'].setValue(menu.parent.id);
    } else {
      this.validateForm.controls['parentName'].setValue('/');
    }

    const menuArray: string[] = menuCode.split(':');

    menu = {
      ...menu, leaf: menu.leaf + '', visible: menu.visible + '',
      openNewPage: menu['openNewPage'] ? menu.openNewPage + '' : '0',
      code: menuArray[menuArray.length - 1]
    };

    this.validateForm.patchValue(menu);
  }
}

1,以上是组件代码。

 


    
    
        
        
        
    
    
        
    
    
    



    
        
            名称
            编码
            菜单图标
            是否显示
            排序
            操作
        
    
    
        
            
                
                    
                        {{ item.name }}
                    
                    
                        {{item.id}}
                    
                    

                    
                        添加子菜单 
                        编辑 
                        删除
                    
                
            
        
    



    
父节点
名称 请输入代码 长度不能超过20 代码
请输入代码 长度不能超过20 只能输入字母和数字
排序码 路由 图标名称 是否叶子节点 是否可见 是否打开新页面

 2,以上是html代码

 

ng-zorro-antd,antd-angular树形数据动态显示操作整理及源码,各自分析拿去用吧,就是没时间整理,整体代码比较乱各位看官随意,勿喷,转载请说明出处。_第1张图片

3,环境版本 

 

4,描述

整体思路在antd官方文档中map数据的格式,围绕着该格式修改数据即可。public mapOfExpandedData: { [key: string]: any[] } = {};

其他的可自由发挥。另ajax框架我用的是axios,以前搞react的时候用惯了。关于后面我业务上的模块会继续完成,框架调好后迫不及待的发个博客。

 

5,捣鼓这个完全是因为武汉肺炎期间闲的蛋疼。

 

6,效果视频__

 

https://v.youku.com/v_show/id_XNDU1MTc1NTYxMg==.html

Google Chrome 2020

 

 

 

 

 

 

 

 

你可能感兴趣的:(ng-zorro-antd,antd-angular树形数据动态显示操作整理及源码,各自分析拿去用吧,就是没时间整理,整体代码比较乱各位看官随意,勿喷,转载请说明出处。)