angular表格宽度拖拽拉宽

1,137 阅读1分钟

项目要求angular表格宽度可拖拽拉伸宽度,项目使用的的为ant-desigin组件库。为了方便使用,将其封装为指令。指令的主代码如下 1、dynamicColumnWidth.directive.ts

/**
 * table宽度的拉伸和记录上次拉伸宽度 并进行初始化赋值(表格中设置nzWidthConfig的话 此拖拽指令会不生效、)
 * 使用方法:
 * 1、单纯拖拽宽度,不需要下次默认显示上次的拖拽宽度
 * th上 [appDynamicColumnWidth]
 * 2、拖拽宽度后 默认显示上次拖拽的宽度
 * 表头th和表格td 上 [appDynamicColumnWidth] [isSetDefaultWidth]="true"
 */
import {Directive, ElementRef, HostListener, Input, OnDestroy, OnInit, Renderer2} from '@angular/core';

@Directive({
    selector: '[appDynamicColumnWidth]',
})
export class DynamicColumnWidthDirective implements OnInit, OnDestroy {
    @Input('appDynamicColumnWidth') appDynamicColumnWidth;
    // minWidth 最小宽度
    @Input('minWidth') minWidth: number;
    // 是否将宽度默认赋值
    @Input('isSetDefaultWidth') isSetDefaultWidth: Boolean = false;
    public originClientX = 0;
    public originClientY = 0;
    public elementWidth = 0;
    public elementHeight = 0;
    public isChanging: Boolean = false;
    private thElement;

    constructor(private el: ElementRef, private rd: Renderer2) {

    }

    ngOnInit() {
        if (this.el.nativeElement.localName === 'th') {
            this.setDragHandle(this.el.nativeElement);
        }
        this.setColumnWidth(this.el.nativeElement);
    }

    /**
     * 设置宽度
     * @param element
     */
    setColumnWidth(element) {
        if (this.isSetDefaultWidth) {
            let columnWidthItems = localStorage.getItem('columnWidth');
            if (columnWidthItems) columnWidthItems = JSON.parse(columnWidthItems);
            const loactionHash = this.getLocationUrl();
            const columnWidthItem = columnWidthItems[loactionHash];
            if (columnWidthItem) element.style.width = columnWidthItem[element.cellIndex];
        }
    }

    /**
     * 将对应拖拽方向 插入可拖拽的dom节点
     */
    setDragHandle(element) {
        const handel = `<div class="dragTableHandel rightHandel" ></div>`;
        this.setColumnWidth(element);
        element.style.position = 'relative';
        element.appendChild(this.createDocumentFragment(handel));
    }


    /***
     * 根据字符串模板创建dom
     * @param templateString
     */
    createDocumentFragment(templateString) {
        return document.createRange().createContextualFragment(templateString);
    }

    /**
     * 元素拖拽节点的 鼠标mounseDown事件,记录初始值
     * @param event
     */
    @HostListener('document:mousedown', ['$event'])
    onHandleMouseDown(event) {
        if (event.target.className && event.target.className.indexOf('dragTableHandel') > -1) {
            this.thElement = event.target.parentElement;
            this.isChanging = true;
            this.originClientX = event.clientX;
            this.originClientY = event.clientY;
            // 获取此时元素的宽高
            this.elementWidth = this.thElement.offsetWidth;
            this.elementHeight = this.thElement.offsetHeight;
        }
    }

    @HostListener('document:mousemove', ['$event'])
    onHandleMouseMove(event) {
        if (this.isChanging) {
            const clientX = event.clientX;
            let width = this.elementWidth + (clientX - this.originClientX);
            if (width < this.minWidth) width = this.minWidth;
            const trElement = this.thElement.offsetParent.querySelector('tbody tr');
            let tdElement;
            // 获取要改变宽度的td
            if (trElement) {
                const tdElements = Array.from(trElement.querySelectorAll('td'));
                tdElement = tdElements[this.thElement.cellIndex];
            }

            if (width) {
                if (tdElement) tdElement.style.width = width + 'px';
                this.thElement.style.width = width + 'px';
            }
        }
    }

    @HostListener('document:mouseup', ['$event'])
    onHandleMouseUp() {
        if (this.thElement && this.thElement.localName === 'th') {
            this.isChanging = false;
            const allPageColumn = localStorage.getItem('columnWidth');
            const loactionHash = window.location.hash;
            let allPageColumnItems = {};
            if (allPageColumn) {
                allPageColumnItems = JSON.parse(allPageColumn);
            }
            this.recordColumnWidth(allPageColumnItems);
        }
    }

    /**
     * 获取当前页面URL
     */
    getLocationUrl() {
        let loactionHash = window.location.hash;
        // 获取当前页面记录的表格列表宽度
        if (loactionHash) loactionHash = loactionHash.split('?')[0];
        return loactionHash;
    }

    /**
     * 记录列宽 保存到本地
     * @param columnItems
     * @param columnWidth
     */
    recordColumnWidth(columnItems: Object = {}, columnWidth: Object = {}) {
        const loactionHash = this.getLocationUrl();
        let pageColumnWidth = columnItems[loactionHash];
        if (!pageColumnWidth) pageColumnWidth = {};
        const index = this.thElement.cellIndex;
        pageColumnWidth[index] = this.thElement.style.width;
        columnItems[loactionHash] = pageColumnWidth;
        localStorage.setItem('columnWidth', JSON.stringify(columnItems));
    }

    ngOnDestroy(): void {
        const dragHandleNodeList = document.querySelectorAll('.dragTableHandel');
        for (let i = 0; i < dragHandleNodeList.length; i++) {
            dragHandleNodeList[i].remove();
        }
    }

}

2、在对应使用指令的module中引入指令。

import {DynamicColumnWidthDirective} from '@shared/dynamicColumnWidth.directive';

@NgModule({
    imports: [
    ],
    declarations: [
        // your components
        DynamicColumnWidthDirective
    ],
    exports: [
       DynamicColumnWidthDirective
    ],
})
export class SharedModule {
}

3、在对应的功能页面使用(当前使用方式会默认保存上次拉伸的宽度,并且进行赋值)

     <nz-table class="bline" [nzData]="cusList" [nzShowPagination]="false"
                                  [nzTotal]="customRequest.total" [(nzLoading)]="customRequest.loading"
                                  [nzScroll]="{ y:'600px'}"
                        >
                            <thead>
                            <tr class="spec-thead-tr">
                                <th nzShowCheckbox nzLeft="0px" [(nzChecked)]="allChecked"
                                    [nzIndeterminate]="indeterminate" (nzCheckedChange)="tableCheckAll($event)">
                                </th>
                                <th nzWidth="100px">
                                    编码
                                </th>
                                <th [appDynamicColumnWidth] [isSetDefaultWidth]="true">
                                    <p>客户名称</p>
                                </th>
                                <th [appDynamicColumnWidth] [isSetDefaultWidth]="true" nzWidth="300">
                                    国家地区
                                </th>
                                <th [appDynamicColumnWidth] [isSetDefaultWidth]="true" nzWidth="200">客户来源</th>
                                <th [appDynamicColumnWidth] [isSetDefaultWidth]="true" nzWidth="200">
                                    <p>客户等级</p>
                                </th>
                       
                            </tr>
                            </thead>
                            <tbody class="spe-tbody">
                            <tr *ngFor="let data of cusList" style="cursor: pointer">
                                <td></td>
                                <td></td>
                               <td [appDynamicColumnWidth] [isSetDefaultWidth]="true"></td>
                               <td [appDynamicColumnWidth] [isSetDefaultWidth]="true"></td>
                               <td [appDynamicColumnWidth] [isSetDefaultWidth]="true"></td>
                               <td [appDynamicColumnWidth] [isSetDefaultWidth]="true"></td>
                            </tr>
                            </tbody>
                        </nz-table>