SlickGrid icon indicating copy to clipboard operation
SlickGrid copied to clipboard

When the grid is hidden and redisplayed, the grid style does not appear properly

Open songjiqiang opened this issue 5 years ago • 27 comments

I found a problem. At the beginning, the grid was hidden. After displaying the grid through jquery show, the grid style was abnormal, the position of the left panel was offset, and the scroll bar was also abnormal.Here is a screenshot of my question:

图片

songjiqiang avatar Sep 19 '19 09:09 songjiqiang

90% of the time, when this happens it's a custom style you've applied. I'd recommend starting with one of the example pages and trying to reproduce the behaviour with the most minimal changes possible.

90% of the time you'll work out what the problem is while you're putting the sample together, and if not then you have a simple example we can reproduce here.

6pac avatar Sep 19 '19 12:09 6pac

This is only a problem if the grid is not visible at the beginning and is later set to be visible, but not if the grid is visible at the beginning

songjiqiang avatar Sep 19 '19 12:09 songjiqiang

We still need a way to reproduce the problem locally. Also, specify the browser and see if it happens in other browsers.

6pac avatar Sep 19 '19 12:09 6pac

This happen when you create the grid inside a container that is hidden. SlickGrid doesn't resize properly when its container is not visible because it cannot calculate the viewport size properly. That was mentioned a few times on Stack Overflow

ghiscoding avatar Sep 19 '19 13:09 ghiscoding

@ghiscoding Yes, as you said, this happens when creating grids in hidden containers, but I tested with official examples and found no problem. The official example is the relative positioning of containers. If there is no relative positioning, there will be this problem, but the relative positioning in my local environment also has this problem.

songjiqiang avatar Sep 19 '19 15:09 songjiqiang

Are you re-rendering on showing the grid? I reiterate: I'd recommend starting with one of the example pages and trying to reproduce the behaviour with the most minimal changes possible. Also, specify the browser and see if it happens in other browsers.

This is the only reliable way we can assist with this.

6pac avatar Sep 19 '19 23:09 6pac

The grid container is initially hidden, then through a button click, the grid's resizeCanvas method is invoked, and when the grid container is displayed, the grid style is distorted image image image image

songjiqiang avatar Oct 10 '19 07:10 songjiqiang

I'm sorry, but you're not following my advice. If you can reproduce the problem with a minimal number of changes to an official example, please post it and I'll take a look.

6pac avatar Oct 10 '19 08:10 6pac

The above screenshot is that I used the official example and made a small change to reproduce this problem. Do I need to re-publish this problem?

songjiqiang avatar Oct 10 '19 09:10 songjiqiang

The fact that you are hiding the grid at first is probably the problem. SlickGrid requires the grid to be shown so that it can calculate the viewport size, if it's hidden it cannot calculate the correct size and you end up with a distorted grid (like you shown).

Screen shot are not a reproducible code sample that we can troubleshoot.

ghiscoding avatar Oct 10 '19 13:10 ghiscoding

My system is a multi-label single page application, where one label page dynamically refreshes the grid in other labels, while the other labels are hidden at this time. The grid style in this application scenario is abnormal.

songjiqiang avatar Oct 10 '19 15:10 songjiqiang

I'm trying to show the grid before refreshing it, but that adds complexity to business development.

songjiqiang avatar Oct 10 '19 15:10 songjiqiang

Like I said earlier, SlickGrid has problem calculating the viewport when the grid is in a hidden container. In your code, try to call the resizeCanvas after the grid is shown, not before.

So try

  1. grid show
  2. resizeCanvas

image

You can see this SO answer as a reference.

ghiscoding avatar Oct 10 '19 16:10 ghiscoding

Have you seen http://6pac.github.io/SlickGrid/examples/example-dynamic-with-jquery-tabs.html ? Also, it's worth mentioning the internal functions cacheCssForHiddenInit() and restoreCssFromHiddenInit. You could probably use those if you need to resize while hidden. They are what the grid uses as a workaround when initialising the grid while hidden - the same logic would apply to resizeCanvas. Perhaps they should be exposed via the API, or perhaps an option on 'ResizeCanvas' could trigger their use.

6pac avatar Oct 11 '19 02:10 6pac

http://6pac.github.io/SlickGrid/examples/example-dynamic-with-jquery-tabs.html I took a look at this example, initializing the grid in a hidden container also works fine, does slickgrid have jquery tabs handled internally? How does this work?

songjiqiang avatar Oct 11 '19 03:10 songjiqiang

The grid uses the internal functions cacheCssForHiddenInit() and restoreCssFromHiddenInit for hidden init, as just mentioned. This modifies the page CSS so that the init works properly, then puts it back the way it was afterwards. Try copying the code and putting it before and after your resizeCanvas call and we'll see if that fixes it. If so, I can make them available for external use.

There is no special allowance for jQuery tabs, anything should work.

6pac avatar Oct 11 '19 04:10 6pac

A little better than before. But it doesn't render properly

图片 图片

songjiqiang avatar Oct 11 '19 05:10 songjiqiang

I'm still willing to help out with this, but you need to provide the test file you are using. Please make sure it works in the example folder of the repo, then drag and drop it to the bottom area of your post.

6pac avatar Oct 24 '19 13:10 6pac

I had to deal with hidden grid today and the best solution is to preset the grid container to opacity: 0, which is basically making the grid invisible (but not hidden) and once you're ready to make it visible then you can change to opacity: 1 which will make it visible. Playing with the Opacity has the advantage of creating the grid with proper size and everything without altering the canvas/viewport size calculations.

We should probably close this issue and just tell users to use opacity instead of display

ghiscoding avatar May 20 '20 14:05 ghiscoding

I think visibility: hidden has the same effect. However they still consume space on the page, it's just rendered as empty space.

6pac avatar May 20 '20 14:05 6pac

That's exactly what I wanted... to consume the space. My grid has auto-resize enabled and when I was showing the grid (with display) it was kinda making the grid jump because for a fraction of a second while was resizing and that was bothering me, however with opacity, it's even resized before I'm ready to show it and doesn't have a jumping side effect. So yeah "consume the space" is what I actually wanted :)

... and you're right, the visibility has the same effect, I'll use that instead. Thx

ghiscoding avatar May 20 '20 15:05 ghiscoding

And I'm still not sure why cacheCssForHiddenInit() doesn't work. It saves hidden parent element styles, and then sets them to position: absolute, visibility: hidden, display: block while the Init process happens. This is essentially exactly what you are suggesting, @ghiscoding (although - last comment - without the position: absolute).

Here's the code:

var cssShow = { position: 'absolute', visibility: 'hidden', display: 'block' };

function cacheCssForHiddenInit() {
  // handle display:none on container or container parents
  $hiddenParents = $container.parents().addBack().not(':visible');
  $hiddenParents.each(function() {
    var old = {};
    for ( var name in cssShow ) {
      old[ name ] = this.style[ name ];
      this.style[ name ] = cssShow[ name ];
    }
    oldProps.push(old);
  });
}

function restoreCssFromHiddenInit() {
  // finish handle display:none on container or container parents
  // - put values back the way they were
  $hiddenParents.each(function(i) {
    var old = oldProps[i];
    for ( var name in cssShow ) {
      this.style[ name ] = old[ name ];
    }
  });
}

It might be worth stepping through the code and seeing what parent elements are being acted upon - it's possible that evolving HTML has mucked this up.

@songjiqiang I still don't know what browser and OS you are using. Looks like Chrome? Version? Windows? Version?

6pac avatar May 20 '20 15:05 6pac

Sounds like it might be worth a setting to specify the startup behaviour around this.

6pac avatar May 20 '20 15:05 6pac

It might be because these position: absolute, display: block might not be what everyone have as their default?! Is that the <div> container that we associate the Grid with? If so, mine has the display: block but has a different position: relative

ghiscoding avatar May 20 '20 15:05 ghiscoding

而且我仍然不确定为什么cacheCssForHiddenInit()不起作用。它节省了隐藏父元素的样式,然后将它们设置为position: absolutevisibility: hiddendisplay: blockInit过程发生。本质上,这正是您所建议的@ghiscoding(尽管-最后一个注释-没有position: absolute)。

这是代码:

var cssShow = { position: 'absolute', visibility: 'hidden', display: 'block' };

function cacheCssForHiddenInit() {
  // handle display:none on container or container parents
  $hiddenParents = $container.parents().addBack().not(':visible');
  $hiddenParents.each(function() {
    var old = {};
    for ( var name in cssShow ) {
      old[ name ] = this.style[ name ];
      this.style[ name ] = cssShow[ name ];
    }
    oldProps.push(old);
  });
}

function restoreCssFromHiddenInit() {
  // finish handle display:none on container or container parents
  // - put values back the way they were
  $hiddenParents.each(function(i) {
    var old = oldProps[i];
    for ( var name in cssShow ) {
      this.style[ name ] = old[ name ];
    }
  });
}

可能值得单步执行代码并查看将要作用于哪些父元素-不断发展的HTML可能将这一点搞砸了。

@songjiqiang我仍然不知道您正在使用什么浏览器和操作系统。看起来像Chrome?版?视窗?版?

This has nothing to do with browser. I tested several browsers, all of which have this problem. The screenshot above is Firefox. Windows 10

songjiqiang avatar May 20 '20 16:05 songjiqiang

@ghiscoding by saving the existing CSS props and then making position: absolute, visibility: hidden, display: block, the code ensures that the grid is not hidden (display: block), not visible (visibility: hidden), but doesn't consume space in the flow (position: absolute). If the container is initially hidden (display: none), it will remain invisible, in this new way, through the Init() process, and then be restored to its initial settings.

6pac avatar May 21 '20 00:05 6pac

@songjiqiang thanks, I'll have a look on the weekend.

6pac avatar May 21 '20 00:05 6pac

a lot has changed since this issue was opened, we dropped jQueryUI, then jQuery, we migrated to TypeScript and we have a new Alpine Theme... so considering how old this issue is and all the changes since then, I think it's fair to close it. Please provide more details if it is still happening

ghiscoding avatar Jan 07 '24 04:01 ghiscoding