How to expand only the visible rows in a large Webix Pro datatable (dynamic height on visible area

Hi @Natalia_Shilova , @Listopad , @webix_B_123
I’m using Webix Pro (v11.x) and have a datatable with thousands of records (virtual scrolling enabled).
For performance reasons, I want to adjust / expand only the currently visible rows (around 20 rows) — not the entire dataset.

Currently, I use a custom method to adjust row height to fit the largest cell text when a row is selected.

/** 
 * @Method resizeRowHeight
 * Adjusts row height based on the largest text content of its cells.
 */
const resizeWebixRowHeight = (rowObj, dataTable) => {
  const colIds = [];
  dataTable.config.columns?.forEach(colObj => colObj.id && colIds.push(colObj.id));

  function processRow(grid, rowObjL) {
    const configuredRowHeights = [grid.config.rowHeight || 24];
    let config;

    for (let i = 0; i < colIds.length; i++) {
      if (colIds[i] === "checkColumn") continue;
      config = grid.getColumnConfig(String(colIds[i]));

      const tempDiv = webix.html.create("DIV", {
        class: "webix_table_cell webix_measure_size webix_cell",
        style: "height:1px; visibility:hidden; white-space: normal !important; position:absolute; top:0px; left:0px; overflow:hidden;word-break:break-all !important;"
      }, "");

      dataTable.$view.appendChild(tempDiv);
      tempDiv.style.width = config.width + "px";

      const cellValue = rowObjL[String(config.id)];
      tempDiv.innerHTML = cellValue ? webix.template.escape(cellValue) : "";
      configuredRowHeights.push(tempDiv.scrollHeight);

      webix.html.remove(tempDiv);
    }

    rowObjL.$height = Math.max.apply(null, configuredRowHeights);
    rowObjL.$css = (rowObjL.$css || "") + " adjustRow";
  }

  const row = dataTable.getItem(rowObj.row);

  if ((row.$css + "").indexOf(" adjustRow") !== -1) {
    row.$css = row.$css.replace(" adjustRow", "");
    row.$height = dataTable.config.rowHeight;
  } else {
    processRow(dataTable, row);
  }

  dataTable.config.__prevAdjustedRow = rowObj.row;
  dataTable.refresh();
};

This works perfectly for a single selected row.
However, now I’d like to expand all currently visible rows only (i.e., the ones rendered in the viewport, ~20 rows) — not the entire dataset (1000+ records).

What I’ve tried

  1. Using getVisibleCount() — works, but I couldn’t find a way to get start/end indexes.
  2. Tried to use getVisibleRange() — seems deprecated in newer versions.

Please suggest me a best solution on this.
Thanks in advance

@Abhishek_Reddy please refer these
https://snippet.webix.com/34596bd1

Hello @Abhishek_Reddy

To get start/end indices please use getScrollState method to get current scroll position.

Using the row height we can get the index of the first visible record:

 const first = Math.floor(state / table.config.rowHeight);

Using the getVisibleCount we can calculate the index of the last one.

Please check the example: Code Snippet

@Natalia_Shilova , @Listopad
What I below requirements to achive

  1. Adjust row height for only the currently selected record (not all rows)

  2. A checkbox to Expand All Rows (auto-fit to content).

  3. When unchecked, revert all rows to their original/compact height.

  4. I’m using custom HTML templates (badges, multi-line content). I want auto-height to work seamlessly with these templates.
    below I have sample custom render temple

const renderMultiSelectColumn = (
  obj: FileNode | webix.obj | RULE_DETAILS_DATA,
  value: string,
  column: webix.WebixDatatableColumn & {
    _filterText?: string;
    _matchCase?: boolean;
    _matchWholeWord?: boolean;
    separator?: string;
  }
) => {
  if (!value) return renderEmptyValue();

  const separator = column.separator || ',';
  const values = value
    .split(separator)
    .map((v) => v.trim())
    .filter(Boolean);
  if (values.length === 0) return renderEmptyValue();

  const adjusted = isRowAdjusted(obj);
  const chips = values.map((val) => {
    const displayText = adjusted ? val : middleEllipsis(val, 20);
    const highlighted = getHighlightedSearchText(
      displayText,
      column._filterText || '',
      undefined,
      adjusted,
      column._matchCase,
      column._matchWholeWord
    );
    const encodedVal = encodeHtml(val);
    return `<span class="chip-item" webix_tooltip="${encodedVal}">${highlighted}</span>`;
  });

  return `<div class="multi-select-chips" webix_tooltip="${encodeHtml(value)}">${chips.join('')}</div>`;
};

export { renderMultiSelectColumn };```

Hello @Abhishek_Reddy ,

Please try this example: Code Snippet

  1. Adjust row height for only the currently selected record (not all rows)

To adjust row height of the currently selected item, you first need to determine the width of the cells excluding paddings and rowLineHeight :

 const item = this.getItem(selection.row)
 const config = this.getColumnConfig(selection.column);
 const width = config.width - webix.skin.$active.dataPadding*2;
 const lineHeight = this.config.rowLineHeight;

Next, you can obtain the raw width of the text in that particular cell (using getText and webix.html.getTextSize ) to calculate the necessary height for the cell:

    const cellContent = this.getText(selection.row, selection.column);
    const size = webix.html.getTextSize(cellContent, "webix_table_cell");
    const cellHeight = lineHeight*Math.ceil(size.width/width);

And using setRowHeight method apply the necessary height.

  1. A checkbox to Expand All Rows (auto-fit to content).

To expand all row please use adjustRowHeight method.

  1. When unchecked, revert all rows to their original/compact height.

To revert all rows you can use each method of the DataStore to iterate the items and apply the default height:

   table.data.each(function (obj) {
        obj.$height = height;
        this.refresh();
   })