Skip to content

Handsontable does not scroll properly when created prior to being added to DOM #11445

@sgerace

Description

@sgerace

Describe the bug

If I initialize a Handsontable instance with an element that does not currently belong to the DOM and then later add the element to the DOM, scrolling does not work properly (I'm guessing other things may not work properly either, but haven't tested thoroughly). The general idea is that I'd like to be able to initialize the Hansontable instance before it exists in the DOM.

Here is a simple stand-alone HTML file that illustrates the issue:

<!DOCTYPE html>
<html>
<head>
    <title ng-bind="title">Handsontable</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/handsontable@14.6.2/dist/handsontable.full.min.css" />
</head>
<body style="flex: 1 1 auto; height: 100vh; position: relative; width: 100%; margin: 0;">

<div id="node" style="flex: 1 1 auto; height: 100%; position: relative; width: 100%;">
  <div id="container" style="bottom: 0; left: 0; overflow: hidden; position: absolute; padding: 0; right: 0; top: 0;"></div>
</div>

<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/handsontable@14.6.2/dist/handsontable.full.min.js"></script>

<script type="text/javascript">

const node = document.querySelector('#node');
const container = document.querySelector('#container');

const observer = new ResizeObserver((entries) => {
  const rect = entries[0].contentRect;
  hot.updateSettings({
    height: rect.height,
    width: rect.width
  });
  hot.render();
});
observer.observe(node);

const hotContainer = document.createElement('div');

const data = [
  ['', 'Tesla', 'Volvo', 'Toyota', 'Ford']
];
for (let i = 0; i < 1000; ++i) {
  data.push([i, 10, 11, 12, 13]);
}

const hot = new Handsontable(hotContainer, {
  data: data,
  rowHeaders: true,
  colHeaders: true,
  licenseKey: 'non-commercial-and-evaluation'
});

// This works:
// container.append(hotContainer);

// This does not work:
setTimeout(() => {
  container.append(hotContainer);
}, 10);

</script>
</body>
</html>

Note that the key to the "non-working" behavior is the fact that the hotContainer is appended to the containing element in a setTimeout to simulate adding the instance after the DOM has been initialized on line 48. Replacing the setTimeout call with an immediate container.append fixes the issue.

I looked through the documentation, but couldn't find any examples or guides on how to properly perform initialization of the Handsontable instance if its element does not belong to the DOM.

setTimeout(() => {
  container.append(hotContainer);
}, 10);

Video/Screenshots

Here is the behavior when hotContainer is appended to container in the provided example within the setTimeout:

handsontable-b0.mp4

Here is the same example working properly, when it is appended outside of setTimeout:

handsontable-b1.mp4

Provide a link to the demo with the bug reproduction

No response

Handsontable version

14.6.2

Framework version

No response

Your environment

macOS, Chrome 133.0.6943.98

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions