Skip to main content Skip to footer

Angular Datagrid Responsive Column Freezing and Pinning

Quick Start Guide
What You Will Need

Wijmo

Angular

Controls Referenced

FlexGrid

Tutorial Concept Responsive Column Freezing and Pinning in an Angular Datagrid - Use Wijmo's FlexGrid control to solve an issue with freezing and pinning columns on smaller screens.

A common feature in DataGrids is Column Freezing (or Pinning). Freezing keeps columns permanently visible on the screen, usually above other columns, and frozen to the left or right of the grid’s ViewPort. As the user scrolls the grid horizontally, the other columns scroll by underneath the frozen columns.

Grid
Grid with two frozen columns shown in yellow

In this blog, we’ll consider the usability challenges that some developers encounter when attempting to freeze columns in applications on smaller screens. We will explore:

Ready to check it out? Download Wijmo Today!

Issues on Smaller Screens

One minor issue with frozen columns is that they can obscure too much of the grid on small screens. This can cause serious accessibility and usability issues.

Smaller grid
Grid with frozen columns on smaller screen (difficult to use)

As you can see above, a DataGrid with frozen columns can become almost unusable on a small screen. As developers, we need to ensure that the features we build are usable and accessible on many different screen sizes and include zoom and font size settings.

So, how do we solve this problem?

Make Column Freezing Responsive 

While working with one of our customers, we formulated a nice idea for handling frozen columns on smaller screens.

The concept:

Unfreeze columns when they take up too much of the Grid’s ViewPort.

We will add a resize handler to the grid and then calculate the width of the frozen column(s) vs. the width of the grid. If the frozen column(s) are over a threshold, then we will unpin them. For this sample, we will set the threshold at 60%. So, if the frozen column(s) fill more than 60% of the grid’s width, we will unfreeze them.

Implementing Our Solution

We will start with a simple instance of Wijmo’s FlexGrid. This sample will be in Angular, but the technique could be applied in any framework or pure JavaScript.

Below is the code featuring our simple Angular DataGrid with columns added, including two that are frozen.

<wj-flex-grid #flexGrid [frozenColumns]="2" (initialized)="handleInitialized(flexGrid)" [itemsSource]="data">
    <wj-flex-grid-filter #filter></wj-flex-grid-filter>
    <wj-flex-grid-column [binding]="'id'" [header]="'Data ID'" [width]="80"></wj-flex-grid-column>
    <wj-flex-grid-column [binding]="'country'" [header]="'Country'"></wj-flex-grid-column>
    <wj-flex-grid-column [header]="'Customer'" [binding]="'customer'" [width]="120"></wj-flex-grid-column>
    <wj-flex-grid-column [binding]="'sales'" [header]="'Sales'"></wj-flex-grid-column>
    <wj-flex-grid-column [binding]="'discount'" [header]="'Discount'"></wj-flex-grid-column>
    <wj-flex-grid-column [binding]="'percentage'" [header]="'Percentage'"></wj-flex-grid-column>
    <wj-flex-grid-column [binding]="'expenses'" [header]="'Expenses'"></wj-flex-grid-column>
    <wj-flex-grid-column [binding]="'isVerified'" [header]="'Is Verified'"></wj-flex-grid-column>
  </wj-flex-grid>

Results:

Results

Now, we need to write the logic for our responsive column freezing. This logic will turn freezing on and off based on the grid size.

First, we determine our threshold. This is the percentage of the window that we will allow the frozen column(s) to fill before unfreezing them. For this example, we will use 60% (or 0.6).

widthPercentage: number = 0.6; // declare percentage value between 0 to 1

Next, we will write the function for freezing and unfreezing. This code is fairly simple. It checks the total width of the frozen column(s) and compares that to the total width of the grid. If the result exceeds our threshold, it unfreezes the columns by setting frozenColumns = 0.

  updateFrozenColumns() {
    const gridWidth = this.flexgrid.controlRect.width;

    // Calculate the total width of the first two columns
    let frozenColumnsWidth = 0;
    for (let i = 0; i < this.frozenColumnsCnt; i++) {
      frozenColumnsWidth += this.flexgrid.columns[i].renderSize;
    }

    // Check if the frozen columns width is more than '60%' of the grid width
    if (frozenColumnsWidth > this.widthPercentage * gridWidth) {
      this.flexgrid.frozenColumns = 0;
    } else {
      this.flexgrid.frozenColumns = 2;
    }
  }

Any time handlers are added for events that can fire frequently, you should consider debouncing them. This will help to avoid performance issues if the event is fired too often. Debouncing simply prevents the event handler from running too many times in a short period.

 // Debounce function to limit the rate at which the update function is called
  private debounce(func: Function, wait: number) {
    return (...args: any[]) => {
      clearTimeout(this.resizeDebounceTimeout);
      this.resizeDebounceTimeout = setTimeout(
        () => func.apply(this, args),
        wait
      );
    };
  }
  private debouncedUpdateFrozenColumns = this.debounce(
    () => this.updateFrozenColumns(),
    50
  );

Finally, we will add the resize handler, which calls our updateFrozenColumns function (debounced).

    // Add resize event listener
    window.addEventListener('resize', () => {
      if (window.devicePixelRatio !== this.lastDevicePixelRatio) {
        this.lastDevicePixelRatio = window.devicePixelRatio;
        this.debouncedUpdateFrozenColumns();
      } else {
        this.debouncedUpdateFrozenColumns();
      }
    });

That’s it! Now, when we reduce the size of our window, we can see that the frozen columns unfreeze and simply act as standard columns.

Unfreeze
Columns unfrozen at smaller screen size

With this small amount of code, we made our frozen columns more accessible and usable!

Bonus Feature: Handle Column Resizing

If you enable column resizing in your grids, you will also want to run the width calculation logic when columns are resized. Users could drag a frozen column to make it wider, which should be accounted for in your logic.

We can easily address this by adding a handler to our resizingColumn event and calling the same updateFrozenColumns function.

grid.resizingColumn.addHandler(this.updateFrozenColumns.bind(this));

Now, if a user resizes a frozen column, it will reevaluate whether the frozen column(s) width is over the threshold.

Ready to try it out? Download Wijmo Today!

Try It Yourself

Check out the final implementation of our sample for Responsive Frozen Columns.

We think this is a clever way to make frozen columns more accessible and usable on smaller screens. We highly recommend considering using this solution in your applications!

Tags:

comments powered by Disqus