Pinning (frozen) of Columns/Rows

Demo

Demo Page / Demo Component

Introduction

One of the requested features, columns or rows pinning (aka frozen). You can pin 1 or more Columns and/or 1 or more Rows. Columns can only be pinned starting from the left side, while Rows can be pinned starting from the Top (default) or Bottom. You can also change the pinning dynamically with setOptions().

Columns/Rows Pinning basic

To set a pinning for the entire duration of the grid, simply use the Grid Options frozenColumn (starting from top) and frozenRow (starting from left), which are both number types.

Component

<script setup lang="ts">
import { type Column, Filters, Formatters, OperatorType, SlickgridVue, SortDirection } from 'slickgrid-vue';
import { onBeforeMount, type Ref } from 'vue';

const gridOptions = ref<GridOption>();
const columnDefinitions: Ref<Column[]> = ref([]);
const dataset = ref<any[]>([]);

onBeforeMount(() => {
  defineGrid();
});

function defineGrid() {
  columnDefinitions.value = [];

  gridOptions.value = {
    alwaysShowVerticalScroll: false, // disable scroll since we don't want it to show on the left pinned columns
    frozenColumn: 2, // number of pinned columns starting from the left
    frozenRow: 3,    // number of pinned columns starting from the top
  }
}
</script>

<template>
  <SlickgridVue gridId="grid1"
    v-model:columns="columnDefinitions"
    v-model:options="gridOptions"
    v-model:data="dataset"
    @onVueGridCreated="vueGridReady($event.detail)"
    @onGridStateChanged="gridStateChanged($event.detail)"
  />
</template>

Caution Please be aware that frozenColumn (left canvas) cannot be wider than the actual grid viewport width and you will get an alert when you try to do this. You can disable it by setting invalidColumnFreezeWidthCallback to undefined (which will still do the validation but it won't show an alert to the end user) or set skipFreezeColumnValidation to completely skip the validation. Also note that if the condition is invalid, it will cancel the action and reapply previous frozenColumn value (unless skip validation is enabled).

Caution Also be aware that you also cannot uncheck (from Column Picker or Grid Menu) more columns than the actual frozenColumn index (in other words, you need to have at least 1, or more, columns on the right section of the freeze/pinning). Also similar as above you can disable it by setting invalidColumnFreezePickerCallback to undefined (which will still do the validation but it won't show an alert to the end user) or set skipFreezeColumnValidation to completely skip the validation. Also note that if the condition is invalid, it will cancel the action and reapply previous frozenColumn value (unless skip validation is enabled).

Rows Pinning starting from bottom

This is basically the same thing as previous code sample, except that you will set the Grid Option property frozenBottom to true and that it's.

Component

<script setup lang="ts">
import { type Column, Filters, Formatters, OperatorType, SlickgridVue, SortDirection } from 'slickgrid-vue';
import { onBeforeMount, type Ref } from 'vue';

const gridOptions = ref<GridOption>();
const columnDefinitions: Ref<Column[]> = ref([]);
const dataset = ref<any[]>([]);

onBeforeMount(() => {
  defineGrid();
});

function defineGrid() {
  // your columns definition
  columnDefinitions.value = [];

  gridOptions.value = {
    alwaysShowVerticalScroll: false, // disable scroll since we don't want it to show on the left pinned columns
    frozenColumn: 2,    // number of pinned columns starting from the left
    frozenRow: 3,       // number of pinned columns (starting from bottom with next property)
    frozenBottom: true, // this will make rows to be pinned starting from the bottom and the number of rows will be 3
  }
}
</script>

Change Pinning Dynamically

You can change the number of pinned columns/rows and even the pinning of columns from top to bottom. For a demo of what that could look like, take a look at the Animated Gif Demo below.

Component

<script setup lang="ts">
import { SlickgridVueInstance } from 'slickgrid-vue';
import { type Column, Filters, Formatters, OperatorType, SlickgridVue, SlickGrid, SortDirection } from 'slickgrid-vue';
import { onBeforeMount, type Ref } from 'vue';

const gridOptions = ref<GridOption>();
const columnDefinitions: Ref<Column[]> = ref([]);
const dataset = ref<any[]>([]);
let gridObj: SlickGrid;

onBeforeMount(() => {
  defineGrid();
});

function defineGrid() {
  columnDefinitions.value = [];

  gridOptions.value = {
    alwaysShowVerticalScroll: false, // disable scroll since we don't want it to show on the left pinned columns
    frozenColumn: 2, // number of pinned columns starting from the left
    frozenRow: 3,    // number of pinned columns starting from the top
  }
}

function vueGridReady(vGrid: SlickgridVueInstance) {
  gridObj = vGrid.slickGrid;
}

/** change dynamically, through slickgrid "setOptions()" the number of pinned columns */
function changeFrozenColumnCount() {
  if (gridObj?.setOptions) {
    gridObj.setOptions({
      frozenColumn: frozenColumnCount
    });
  }
}

/** change dynamically, through slickgrid "setOptions()" the number of pinned rows */
function changeFrozenRowCount() {
  if (gridObj?.setOptions) {
    gridObj.setOptions({
      frozenRow: frozenRowCount
    });
  }
}

/** toggle dynamically, through slickgrid "setOptions()" the top/bottom pinned location */
function toggleFrozenBottomRows() {
  if (gridObj?.setOptions) {
    gridObj.setOptions({
      frozenBottom: !isFrozenBottom
    });
    isFrozenBottom = !isFrozenBottom; // toggle the variable
  }
}
</script>

<template>
  <div class="row">
    <div class="col-sm-12">
      <span>
        <label htmlFor="">Pinned Rows: </label>
        <input type="number" :value="frozenRowCount" @input="changeFrozenRowCount($event)" />
        <button class="btn btn-outline-secondary btn-xs btn-icon" @click="setFrozenRowCount()">
          Set
        </button>
      </span>
      <span style={{ marginLeft: '10px' }}>
        <label htmlFor="">Pinned Columns: </label>
        <input type="number" :value="frozenColumnCount" @input="changeFrozenColumnCount($event)" />
        <button class="btn btn-outline-secondary btn-xs btn-icon" @click="setFrozenColumnCount()">
          Set
        </button>
      </span>
    </div>
  </div>
</template>

Animated Gif Demo

Last updated