Angular Mat Table添加mat-sort-header后resizeColumn列宽调整失效如何解决
问题根因
冲突来源于两点:
mat-sort-header会自动拦截表头的所有鼠标事件,你插入的拖拽触发元素的mousedown事件被冒泡拦截后无法触发拖拽逻辑mat-header-cell默认设置了flex: 1 1 auto属性,作为flex容器的子项,直接设置width属性不会生效,flex布局会自动重算宽度
修复方案
1. 修改自定义resizeColumn指令代码
核心修改两处逻辑:
- 拖拽触发时阻止事件冒泡,避免触发排序逻辑
- 设置宽度时同时覆盖flex属性,强制固定宽度生效
修改后的完整指令代码如下:
import { Directive,OnInit, Renderer2, Input, ElementRef} from '@angular/core'; @Directive({ selector: '[resizeColumn]' }) export class ResizecolDirective implements OnInit { @Input("resizeColumn") resizable!:boolean; private startX!:number; private startWidth!:number; private column!: HTMLElement; private table!: HTMLElement; private pressed!: boolean; constructor(private renderer: Renderer2, private el: ElementRef) { this.column = this.el.nativeElement; } ngOnInit(){ if (this.resizable) { const row = this.renderer.parentNode(this.column); const thead = this.renderer.parentNode(row); this.table = this.renderer.parentNode(thead); const resizer = this.renderer.createElement("span"); this.renderer.addClass(resizer, "resize-holder"); this.renderer.appendChild(this.column, resizer); this.renderer.listen(resizer, "mousedown", this.onMouseDown); this.renderer.listen(this.table, "mousemove", this.onMouseMove); this.renderer.listen("document", "mouseup", this.onMouseUp); } } onMouseDown = (event: MouseEvent) => { // 阻止事件冒泡和默认行为,避免触发排序 event.stopPropagation(); event.preventDefault(); this.pressed = true; this.startX = event.pageX; this.startWidth = this.column.offsetWidth; }; onMouseMove = (event: MouseEvent) => { const offset = 30; if (this.pressed && event.buttons) { this.renderer.addClass(this.table, "resizing"); let width =this.startWidth + (event.pageX - this.startX - offset); // 同时覆盖flex和宽度相关属性,强制固定宽度生效 this.renderer.setStyle(this.column, "flex", `0 0 ${width}px`); this.renderer.setStyle(this.column, "width", `${width}px`); this.renderer.setStyle(this.column, "max-width", `${width}px`); } }; onMouseUp = (event: MouseEvent) => { if (this.pressed) { this.pressed = false; this.renderer.removeClass(this.table, "resizing"); } }; }
2. 添加全局样式保证拖拽触发区正常显示
在项目的全局样式文件(比如styles.scss)中添加以下样式:
.resize-holder { position: absolute; top: 0; right: 0; width: 12px; height: 100%; cursor: col-resize; z-index: 999; background: transparent; } th.mat-header-cell { position: relative; overflow: visible; } table.resizing * { user-select: none !important; }
3. 原有模板无需修改
你的表格代码可以保留mat-sort-header属性,不需要做额外调整,排序和列宽调整功能可以同时生效。
内容的提问来源于stack exchange,提问作者Vikash Mishra
相关产品推荐
相关产品推荐

