基于angular10、angular-material写的下拉组织树

效果图:

<mat-form-field class="mat-block" [formGroup]="dropdownTreeFormGroup">
    <mat-label>{{label}}</mat-label>
    <input type="text" matInput formControlName="treeNodeName" #treeSelectInput [required]="required" readonly
        [matMenuTriggerFor]="menu"  #dropDownTreeMenu="matMenuTrigger" (menuOpened)="menuOpened()" >
    <mat-menu #menu="matMenu" xPosition="after" >
        <div class="tb-user-menu-items meunContent">
            <div *ngIf="treeListData.length>0">
                <ng-container *ngTemplateOutlet="treeNode;context:{$implicit:treeListData}">
                </ng-container>
                <ng-template #treeNode let-itemNode>
                    <ng-container *ngFor="let item of itemNode">
                        <div mat-menu-item (click)="selectTreeNode($event,item)" class="treeItem"
                            [ngStyle]="{'padding-left':item.level * 20 + 'px'}">
                            <button mat-icon-button>
                                <mat-icon class="material-icons" (click)="handleOpen($event,item)"
                                    *ngIf="item.children&&item.children.length>0">{{
                                    item.open? 'expand_less'
                                    : 'expand_more' }}</mat-icon>
                            </button>
                            <span>{{item[renderKey]}}</span>
                        </div>
                        <ng-container *ngIf="item.children&&item.children.length>0 && item.open">
                            <ng-container *ngTemplateOutlet="treeNode;context:{$implicit:item.children}"></ng-container>
                        </ng-container>
                    </ng-container>
                </ng-template>
            </div>
            <div *ngIf="treeListData.length==0" class="noDataModal_treeSelect" [fxShow]="showDropDown">
                <span>暂无数据</span>
            </div>
        </div>
    </mat-menu>
</mat-form-field>

ts:

import { Component, Input, OnInit, ViewChild, NgZone, ElementRef, forwardRef, Output, EventEmitter, SimpleChanges, OnChanges } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
import { DeviceProfileId } from '@shared/models/id/device-profile-id';
import { Observable, of } from 'rxjs';
import { Direction } from '@shared/models/page/sort-order';
import { map, mergeMap, share, tap, startWith } from 'rxjs/operators';
import { DeviceTypeService } from '@core/http/device-type.service';
import { DeviceProfile, DeviceTypeInfo, DeviceTransportType } from '@shared/models/device.models';
import { PageLink } from '@shared/models/page/page-link';
import { TranslateService } from '@ngx-translate/core';
import { MatMenuTrigger } from '@angular/material/menu';
import * as $ from "jquery"
@Component({
  selector: 'tb-dropdown-tree',
  templateUrl: './tb-dropdown-tree.component.html',
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => DropDownTreeComponent),
    multi: true
  }],
  styleUrls: ['./tb-dropdown-tree.component.scss']
})
export class DropDownTreeComponent implements ControlValueAccessor, OnInit, OnChanges {
  @ViewChild('dropDownTreeMenu', {static: true}) dropDownTreeMenu: MatMenuTrigger;
  @Input() itemNode
  @Input() required: boolean = false;
  @Input() label: string = "";
  @Input() placeholder: string = "";

  isEditValue = true;//编辑
  @Input()
  set isEdit(edit: boolean) {
    this.isEditValue = edit;
    if (this.dropdownTreeFormGroup) {
      if (!edit) {
        this.dropdownTreeFormGroup.get('treeNodeName').disable({ emitEvent: false }); //设置disable
      } else {
        this.dropdownTreeFormGroup.get('treeNodeName').enable({ emitEvent: false });//取消disable
      }
    }
  }

  get isEdit() {
    return this.isEditValue
  }


  @Input()
  set treeList(data) {
    if (data && data.length > 0) {
      this.treeListData = data;
      this.addTreeOpenValue(this.treeListData);//添加open值
    }
  }

  @Input() autocompleteKey: any = "name"; //循环取的key

  @Input()
  set treeModalValue(nodeValue:string){
    if(this.dropdownTreeFormGroup&&nodeValue!=="defaultValve"){
      this.dropdownTreeFormGroup.patchValue({treeNodeName:nodeValue})
    }
  }

  @Input()
  renderKey = "title";//页面渲染的key值

  @Input()
  transportType: DeviceTransportType = null;



  @Output()
  selectOrgNode = new EventEmitter<DeviceTypeInfo>();

  @ViewChild('treeSelectInput', { static: true }) treeSelectInput: ElementRef;
  dropdownTreeFormGroup: FormGroup;
  showDropDown: boolean = false;
  private dirty = false;
  treeListData = [];//组织树
  filteredDeviceTypes: Observable<Array<DeviceTypeInfo>>
  private propagateChange = (v: any) => { };

  constructor(
    private fb: FormBuilder,
    private deviceTypeService: DeviceTypeService,
    public translate: TranslateService,
    private zone: NgZone,
  ) {
    this.dropdownTreeFormGroup = this.fb.group({
      treeNodeName: [null]
    });
  }
  ngOnInit() {
    window.addEventListener('resize', () => {
      this.setDropDownStyle();
    })
  }


  menuOpened(){
    this.setDropDownStyle();
  }
  setDropDownStyle() {
    let inputWidth = $(this.treeSelectInput.nativeElement).width();
    setTimeout(()=>{
      $('.mat-menu-panel').css({maxWidth:2000});
      $('.cdk-overlay-container').find('.meunContent').css({width: inputWidth});
    },10)
  }

  handleTreeModal($event) {
    if ($event) {
      $event.stopPropagation();
      $event.preventDefault();
    }
    this.showDropDown = !this.showDropDown;
    if(this.showDropDown ){
      this.setDropDownStyle();
    }
  }


  selectTreeNode($event, item) {
    if ($event) {
      $event.stopPropagation();
      $event.preventDefault();
    }
    this.dropdownTreeFormGroup.patchValue({ treeNodeName: item[this.renderKey]})
    this.selectOrgNode.emit(item)
    this.dropDownTreeMenu.closeMenu()
  }
  // 数据增加open值
  addTreeOpenValue(listData, level = 1) {
    for (let item of listData) {
      if (item.children && item.children.length > 0) {
        this.addTreeOpenValue(item.children, level + 1);
      }
      item.level = level;
      item.open = false;
    }
  }


  handleOpen($event, item) {
    if ($event) {
      $event.stopPropagation();
      $event.preventDefault();
    }
    item.open = !item.open;
  }
  registerOnChange(fn: any): void {
    this.propagateChange = fn;
  }

  updateView(deviceProfile: DeviceTypeInfo | null) {

  }

  ngOnChanges(changes: SimpleChanges): void {

  }

  writeValue(value: DeviceProfileId | null): void {

  }

  registerOnTouched(fn: any): void {

  }

}

引用

<!-- 下拉组织树 -->
        <tb-dropdown-tree label="所属组织" *ngIf="showOrgForm" [treeModalValue]="treeModalValue"  [isEdit]="orgTreeIsEdit"  (selectOrgNode)="selectOrgNode($event)" [required]="true" [treeList]="treeList"></tb-dropdown-tree>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值