Resize table column — Angular

Debasis Panda
3 min readMar 19, 2020

--

Resizable Table

Table is a very important part of web application and when it comes to a complex table displaying content is a real challenge.

There are many ways we can organize our table content so that it can be properly readable. We will discuss one of those option i.e- table column sizing.

As part of this story we will learn how to implement column resize to a angular material table.

I expect that we have a table ready to which we have to apply resize feature. So let’s skip this part to make the story short. You can create one using this tutorial.

We can directly add the resize functionality to the table component but for better code management let’s move the logic to a directive so this can be re-used in other places.

So let’s create our directive.

import { Directive, OnInit } from "@angular/core";@Directive({
selector: "[resizeColumn]"
})
export class ResizeColumnDirective implements OnInit {
// Whether column need resizing or not
@Input("resizeColumn") resizable: boolean;
constructor(){} ngOnInit(){
//to-do
}
}

Next we should define our properties for manipulating columns width.

import { Directive, OnInit } from "@angular/core";@Directive({
selector: "[resizeColumn]"
})
export class ResizeColumnDirective implements OnInit {
// Whether column need resizing or not
@Input("resizeColumn") resizable: boolean;
@Input() index: number; private startX: number; private startWidth: number; private column: HTMLElement; private table: HTMLElement; private pressed: boolean; constructor(private el: ElementRef){
this.column = this.el.nativeElement;
}
ngOnInit(){
//to-do
}
}

Next we need to add events for handling column resize. As we are adding resize with mouse we will mostly depend on three events Mouse Down, Mouse UP and Mouse Move. Lets see how we can write those events.

We will make use of Renderer2 for adding event to column elements.

ngOnInit() {
if (this.resizable) {
const row = this.renderer.parentNode(this.column);
const thead = this.renderer.parentNode(row);
this.table = this.renderer.parentNode(thead);
// we will add this element as a marker for triggering resize.
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) => {}onMouseMove = (event: MouseEvent) => {}onMouseUp = (event: MouseEvent) => {}

Now our event are ready and we can verify by doing respective action on table cell. Let write our main logic for resize inside event handler methods.

onMouseDown = (event: MouseEvent) => {
this.pressed = true;
this.startX = event.pageX;
this.startWidth = this.column.offsetWidth;
};
onMouseMove = (event: MouseEvent) => {
const offset = 35;
if (this.pressed && event.buttons {
this.renderer.addClass(this.table, "resizing");
// Calculate width of column
let width = this.startWidth + (event.pageX - this.startX - offset);
const tableCells = Array
.from(this.table.querySelectorAll(".mat-row"))
.map((row: any) => row.querySelectorAll(".mat-cell")
.item(this.index));
// Set table header width
this.renderer.setStyle(this.column, "width", `${width}px`);
// Set table cells width
for (const cell of tableCells) {
this.renderer.setStyle(cell, "width", `${width}px`);
}
}
};
onMouseUp = (event: MouseEvent) => {
if (this.pressed) {
this.pressed = false;
this.renderer.removeClass(this.table, "resizing");
}
};

Demo: https://angular-table-resize.stackblitz.io

Source: https://stackblitz.com/edit/angular-table-resize

Thanks for reading.

--

--

Debasis Panda

I code JavaScript, Angular, React, Node, Python etc. Love to travel and write things in free time.