Skip to main content

DHTMLX Pivot. Custom frozen (fixed) columns (your number) example

Demo of custom frozen (fixed) columns in DHTMLX Pivot. Dynamically freeze left and right columns using the render-table event to set split positions based on the current pivot configuration state.

Live example

const widget = new pivot.Pivot("#pivot", {
    fields,
    data: dataset,
    config: {
        rows: [
            "hobbies"
        ],
        columns: [
            "favorite_pet",
        ],
        values: [
            {
                field: "height",
                method: "max"
            }
        ]
    },
    columnShape: {
        autoWidth: {
            columns: {
                favorite_pet: true,
                weight: true,
                height: true,
            },
        },
    },
});

widget.api.on("render-table", ({ config: tableConfig }) => {
    const { rows, values } = widget.api.getState().config;
    tableConfig.split = {
        left: rows.length + values.length,
        right: values.length
    };
});
<!-- component container -->
<div id="pivot" style="width: 100%; height: 100%;"></div>

<!-- dataset -->

<script>
const dataset = [
      {
        "name": "Alex",
        "age": 30,
        "height": 170,
        "weight": 74,
        "hobbies": "Photography",
        "favorite_color": "Blue",
        "favorite_pet": "Dog",
        "relationship_status": "Married",
        "favorite_book": "Master and Margarita",
        "music": "Rock",
        "favorite_video_game": "The Witcher",
        "education_level": "High school diploma",
        "language": "English",
        "favorite_dish": "Sushi",
        "favorite_drink": "Coffee",
        "favorite_dessert": "Chocolate Cake",
        "activities": "Yoga",
        "activity_level": "High",
        "fashion_style": "Casual",
        "places_to_visit": "Japan",
        "movie_preferences": "Drama",
        "personality_type": "Leader, extrovert",
        "superhero_power": "Teleportation",
        "favorite_season": "Autumn",
        "communication_style": "Direct",
        "chronotype": "Night owl",
        "preferred_weather": "Sunny"
      },
      {
        "name": "Robert",
        "age": 25,
        "height": 181,
        "weight": 65,
        "hobbies": "Traveling",
        "favorite_color": "Green",
        "favorite_pet": "Cat",
        "relationship_status": "In a relationship",
        "favorite_book": 1984,
        "music": "Pop",
        "favorite_video_game": "Animal Crossing",
        "education_level": "Doctorate",
        "language": "Spanish",
        "favorite_dish": "Pizza",
        "favorite_drink": "Tea",
        "favorite_dessert": "Cheesecake",
        "activities": "Running",
        "activity_level": "Moderate",
        "fashion_style": "Classic",
        "places_to_visit": "Norway",
        "movie_preferences": "Romance",
        "personality_type": "Analyst, introvert",
        "superhero_power": "Time manipulation",
        "favorite_season": "Winter",
        "communication_style": "Expressive",
        "chronotype": "Early bird",
        "preferred_weather": "Rainy"
      },
      // ... 203 more items (see Live Editor for full data)
    ]; 

    const fields = [
      {
        "id": "name",
        "label": "Name",
        "type": "text"
      },
      {
        "id": "age",
        "label": "Age",
        "type": "number"
      },
      {
        "id": "height",
        "label": "Height",
        "type": "number"
      },
      {
        "id": "weight",
        "label": "Weight",
        "type": "number"
      },
      {
        "id": "hobbies",
        "label": "Hobbies",
        "type": "text"
      },
      {
        "id": "favorite_color",
        "label": "Favorite color",
        "type": "text"
      },
      {
        "id": "favorite_pet",
        "label": "Favorite pet",
        "type": "text"
      },
      {
        "id": "relationship_status",
        "label": "Relationship status",
        "type": "text"
      },
      {
        "id": "favorite_book",
        "label": "Favorite book",
        "type": "text"
      },
      {
        "id": "music",
        "label": "Music",
        "type": "text"
      },
      {
        "id": "favorite_video_game",
        "label": "Favorite video game",
        "type": "text"
      },
      {
        "id": "education_level",
        "label": "Education level",
        "type": "text"
      },
      {
        "id": "language",
        "label": "Language",
        "type": "text"
      },
      {
        "id": "favorite_dish",
        "label": "Favorite dish",
        "type": "text"
      },
      {
        "id": "favorite_drink",
        "label": "Favorite drink",
        "type": "text"
      },
      {
        "id": "favorite_dessert",
        "label": "Favorite dessert",
        "type": "text"
      },
      {
        "id": "activities",
        "label": "Activities",
        "type": "text"
      },
      {
        "id": "activity_level",
        "label": "Activity level",
        "type": "text"
      },
      {
        "id": "fashion_style",
        "label": "Fashion style",
        "type": "text"
      },
      {
        "id": "places_to_visit",
        "label": "Places to visit",
        "type": "text"
      },
      {
        "id": "movie_preferences",
        "label": "Movie preferences",
        "type": "text"
      },
      {
        "id": "personality_type",
        "label": "Personality type",
        "type": "text"
      },
      {
        "id": "superhero_power",
        "label": "Superhero power",
        "type": "text"
      },
      {
        "id": "favorite_season",
        "label": "Favorite season",
        "type": "text"
      },
      {
        "id": "communication_style",
        "label": "Communication style",
        "type": "text"
      },
      {
        "id": "chronotype",
        "label": "Chronotype",
        "type": "text"
      },
      {
        "id": "preferred_weather",
        "label": "Preferred weather",
        "type": "text"
      }
  	];
</script>

Pivot tables with many column groups can extend far beyond the visible viewport. When scrolling horizontally, users lose sight of the row labels on the left and may also need summary columns pinned on the right. A static freeze configuration breaks when users dynamically change rows or values through the configuration panel.

DHTMLX Pivot supports frozen columns through the render-table event, which fires before the internal grid renders. By intercepting this event and setting tableConfig.split.left and tableConfig.split.right, you can freeze a custom number of columns on either side. The key advantage is that you can calculate the freeze positions dynamically from the current pivot state, so the frozen columns adapt automatically when the user modifies the configuration.

This example demonstrates dynamic frozen columns applied to a personal data survey. The render-table handler reads the current rows and values counts from widget.api.getState().config, then freezes rows.length + values.length columns on the left and values.length columns on the right. Use this approach when you need frozen columns that stay correct regardless of how users reconfigure the pivot.

Solution overview

To set custom frozen columns, listen to the render-table event on the pivot's API. The event provides a config object (aliased as tableConfig) representing the internal grid configuration. Set tableConfig.split.left to the number of columns to freeze on the left, and tableConfig.split.right for the right side. Use widget.api.getState().config to read the current rows and values arrays dynamically.

Key points

  • Dynamic freeze positions: The split values are calculated from the live pivot state, so frozen columns adjust automatically when users add or remove rows/values via the configuration panel
  • Left and right freezing: The tableConfig.split object supports both left and right properties, allowing you to pin columns on either edge of the table
  • Event-driven approach: The render-table event fires before each grid render, ensuring the freeze configuration is always up to date
  • Combined with auto width: This example pairs frozen columns with columnShape.autoWidth for optimal column sizing alongside the freeze behavior

API reference

  • Pivot render-table event: Event that fires before the internal grid renders, providing access to the table configuration.
  • Pivot api.getState(): Method to retrieve the current pivot configuration including rows, columns, and values.
  • Pivot columnShape: Configuration for column appearance including auto width settings.

Additional resources