Skip to content

Column Stretch

RevoGrid provides the ability to automatically adjust the width of columns to fit the table’s width. This is particularly useful when you have fewer columns than needed to enable the horizontal scrollbar, and you want to distribute the available space evenly or according to specific criteria.

Source code
TypeScript ts
// src/components/column-stretch/columnStretch.ts

import { defineCustomElements } from '@revolist/revogrid/loader';
defineCustomElements();

import { currentTheme, useRandomData } from '../composables/useRandomData';
const { createRandomData } = useRandomData();
const { isDark } = currentTheme();

import { ColumnStretchPlugin } from '@revolist/revogrid-pro';

function createForm(container: HTMLElement, onStretchChange: (value: string) => void) {
  const form = document.createElement('div');
  form.className = 'rv-btn-group mb-2';

  const options = [
    { value: 'all', label: 'All', checked: true },
    { value: 'last', label: 'Last' },
    { value: '2nd', label: '2nd' },
    { value: 'none', label: 'None' }
  ];

  options.forEach(option => {
    const label = document.createElement('label');
    label.className = 'rv-btn-group-item';
    const input = document.createElement('input');
    input.type = 'radio';
    input.name = 'stretch';
    input.value = option.value;
    input.checked = option.checked || false;
    input.addEventListener('change', () => onStretchChange(option.value));
    
    const text = document.createElement('span');
    text.textContent = option.label;
    label.appendChild(input);
    label.appendChild(text);
    form.appendChild(label);
  });

  container.appendChild(form);
}

function createGrid(container: HTMLElement) {
  const grid = document.createElement('revo-grid');
  grid.setAttribute('resize', '');
  grid.setAttribute('hide-attribution', '');
  grid.style.minHeight = '250px';
  container.appendChild(grid);
  return grid;
}

export function load(parentSelector: string) {
  const parent = document.querySelector(parentSelector);
  if (!parent) return;

  // Create form and grid elements
  const grid = createGrid(parent);
  createForm(parent, (value) => {
    Object.assign(grid, {
      stretch: value === '2nd' ? 1 : value
    })
  });

  // Configure grid
  grid.source = createRandomData(100);
  grid.columns = [
    {
      name: '🆔 ID',
      prop: 'id',
    },
    {
      name: '🍎 Fruit',
      prop: 'name',
    },
    {
      name: '💰 Price',
      prop: 'price',
    },
  ];

  Object.assign(grid, {
    stretch: 'all'
  })
  
  grid.plugins = [ColumnStretchPlugin] as any;
  grid.theme = isDark() ? 'darkCompact' : 'compact';
  grid.hideAttribution = true;
}
Vue vue
<template>
  <div>
    <div class="rv-btn-group mb-2">
      <label v-for="mode in ['all', 'last', '2nd', 'none']" :key="mode" class="rv-btn-group-item">
        <input type="radio" name="stretch" :value="mode" v-model="stretchMode" />
        <span>{{ mode.charAt(0).toUpperCase() + mode.slice(1) }}</span>
      </label>
    </div>

    <RevoGrid
      class="grow h-full cell-border"
      :theme="isDark ? 'darkMaterial' : 'material'"
      :columns="columns"
      :source="source"
      :plugins="plugins"
      :stretch="stretch"
      resize
      hide-attribution
      style="min-height: 250px;"
    />
  </div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue';
import RevoGrid from '@revolist/vue3-datagrid';
import { ColumnStretchPlugin, RowOddPlugin, RowSelectPlugin } from '@revolist/revogrid-pro';
import { useRandomData, currentThemeVue } from '../composables/useRandomData';

const { createRandomData } = useRandomData();
const { isDark } = currentThemeVue();

const stretchMode = ref('all');
const source = ref(createRandomData(100));

const columns = [
  {
    name: 'ID',
    prop: 'id',
    rowSelect: true,
  },
  {
    name: 'Fruit',
    prop: 'name',
  },
  {
    name: 'Price',
    prop: 'price',
  },
];

const plugins = [ColumnStretchPlugin, RowOddPlugin, RowSelectPlugin];

const stretch = computed(() => stretchMode.value === '2nd' ? 1 : stretchMode.value);
</script> 
React tsx
import React, { useState } from 'react';
import { RevoGrid } from '@revolist/react-datagrid';
import { ColumnStretchPlugin } from '@revolist/revogrid-pro';
import { useRandomData, currentTheme } from '../composables/useRandomData';

const { createRandomData } = useRandomData();
const { isDark } = currentTheme();

export const ColumnStretchExample = () => {
  const [stretchMode, setStretchMode] = useState('all');
  const [source] = useState(() => createRandomData(100));

  const columns = [
    {
      name: '🆔 ID',
      prop: 'id',
    },
    {
      name: '🍎 Fruit',
      prop: 'name',
    },
    {
      name: '💰 Price',
      prop: 'price',
    },
  ];

  const handleStretchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setStretchMode(e.target.value);
  };

  return (
    <div>
      <div className="rv-btn-group mb-2">
        {(['all', 'last', '2nd', 'none'] as const).map((mode) => (
          <label key={mode} className="rv-btn-group-item">
            <input
              type="radio"
              name="stretch"
              value={mode}
              checked={stretchMode === mode}
              onChange={handleStretchChange}
            />
            <span>{mode.charAt(0).toUpperCase() + mode.slice(1)}</span>
          </label>
        ))}
      </div>

      <RevoGrid
        columns={columns}
        source={source}
        theme={isDark() ? 'darkCompact' : 'compact'}
        plugins={[ColumnStretchPlugin] as any}
        stretch={stretchMode === '2nd' ? 1 : stretchMode}
        resize
        hideAttribution
        style={{ minHeight: '250px' }}
      />
    </div>
  );
}; 
Angular ts
import { Component, OnInit } from '@angular/core';
import { RevoGrid } from '@revolist/angular-datagrid';
import { ColumnStretchPlugin } from '@revolist/revogrid-pro';
import { useRandomData, currentTheme } from '../composables/useRandomData';

const { createRandomData } = useRandomData();
const { isDark } = currentTheme();

@Component({
  selector: 'column-stretch-grid',
  standalone: true,
  imports: [RevoGrid],
  template: `
    <div class="rv-btn-group mb-2">
      <label class="rv-btn-group-item">
        <input
          type="radio"
          name="stretch"
          value="all"
          [checked]="stretchMode === 'all'"
          (change)="onStretchChange($event)"
        />
        <span>All</span>
      </label>
      <label class="rv-btn-group-item">
        <input
          type="radio"
          name="stretch"
          value="last"
          [checked]="stretchMode === 'last'"
          (change)="onStretchChange($event)"
        />
        <span>Last</span>
      </label>
      <label class="rv-btn-group-item">
        <input
          type="radio"
          name="stretch"
          value="2nd"
          [checked]="stretchMode === '2nd'"
          (change)="onStretchChange($event)"
        />
        <span>2nd</span>
      </label>
      <label class="rv-btn-group-item">
        <input
          type="radio"
          name="stretch"
          value="none"
          [checked]="stretchMode === 'none'"
          (change)="onStretchChange($event)"
        />
        <span>None</span>
      </label>
    </div>

    <revo-grid
      [source]="source"
      [columns]="columns"
      [plugins]="plugins"
      [stretch]="stretch"
      [theme]="theme"
      [hideAttribution]="true"
      style="min-height: 250px;"
      resize
    ></revo-grid>
  `,
})
export class ColumnStretchGridComponent implements OnInit {
  stretchMode: string = 'all';
  source = createRandomData(100);
  theme = isDark() ? 'darkCompact' : 'compact';
  plugins = [ColumnStretchPlugin] as any;

  columns = [
    {
      name: '🆔 ID',
      prop: 'id',
    },
    {
      name: '🍎 Fruit',
      prop: 'name',
    },
    {
      name: '💰 Price',
      prop: 'price',
    },
  ];

  stretch: string | number = this.stretchMode;

  ngOnInit() {
    // Any initialization if needed
  }

  onStretchChange(event: Event) {
    const target = event.target as HTMLInputElement;
    this.stretchMode = target.value;
    this.stretch = this.stretchMode === '2nd' ? 1 : this.stretchMode;
  }
} 

In this article, we’ll walk you through the process of implementing column stretching in RevoGrid using the ColumnStretchPlugin. We’ll also explore the different configurations available for stretching the columns.

Column stretching is a feature which allows you to automatically adjust the width of columns to fit the entire width of the table. The width of each column is calculated based on the number of columns and their respective sizes, ensuring the grid’s width is fully utilized. This feature is especially useful when working with a small number of columns.

Important Note

The Column Stretch plugin may conflict with other column size configurations. The following cases will prevent column stretching:

  • Columns with explicit size property set
  • Columns with autoSize enabled
  • When the total width of all columns exceeds the available space (negative remaining width)

In these cases, the stretch configuration will be ignored for those specific columns to preserve their intended sizing behavior.

RevoGrid supports different types of stretch configurations through the StretchConfig type:

  • 'none': No column stretching will be applied. Columns retain their default width.

  • 'last': Only the last column will stretch to fill the remaining width.

  • 'all': All columns will stretch evenly to fill the table’s width.

  • number: A specific column (by index) will stretch to fill the remaining width.

  • To stretch only the last column:

    grid.additionalData = { stretch: 'last' };
  • To stretch a specific column by index (e.g., the second column):

    grid.additionalData = { stretch: 1 };
  • To stretch all columns evenly:

    grid.additionalData = { stretch: 'all' };

By using the ColumnStretchPlugin, you can easily manage the width of columns in RevoGrid, making sure your table layout looks clean and is fully utilized. Whether you want to stretch all columns evenly or just the last one, this plugin offers flexibility to suit your needs.

Experiment with the different stretch configurations to see which works best for your data grid!