Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple FlexBox layouts in a container can cause resize loop #2701

Closed
philippjfr opened this issue Sep 1, 2021 · 5 comments · Fixed by #4452
Closed

Multiple FlexBox layouts in a container can cause resize loop #2701

philippjfr opened this issue Sep 1, 2021 · 5 comments · Fixed by #4452
Milestone

Comments

@philippjfr
Copy link
Member

When placing multiple FlexBoxes in a container they can cause a resize loop due to their after_layout script:

    _scripts = {'after_layout': """
    if (view.parent != null && view._has_finished && !state.resizing) {
      state.resizing = true
      view.parent.invalidate_layout()
      state.resizing = false
    }
    """}
@philippjfr philippjfr added this to the 0.12.2 milestone Sep 1, 2021
@philippjfr
Copy link
Member Author

@sdc50 If you can find a simple example of this happening that would be super helpful, my naive examples didn't have this problem.

@philippjfr philippjfr modified the milestones: 0.12.2, v0.12.x Sep 20, 2021
@sdc50
Copy link
Contributor

sdc50 commented Sep 24, 2021

find a simple example of this happening

I'm still trying to pinpoint what is causing this, but it has something to do with adding some custom JS with an event lister for window.onresize.

@sdc50
Copy link
Contributor

sdc50 commented Dec 17, 2021

@philippjfr Okay, I've finally been able to reproduce this error on a simplified example. It's a little strange to me, but the key to causing the error seems to be using template.main.append. If I use extend then it works great.

import random
import panel as pn
import param

rcolor = lambda: "#%06x" % random.randint(0, 0xFFFFFF)
rrange = lambda: range(random.randint(2, 10))

number_of_groups = 8 

groups = [rrange() for i in range(number_of_groups)]

items = [pn.FlexBox(*[pn.pane.HTML(str(i), background=rcolor(), width=100, height=100) for i in g]) for g in groups]

templ = pn.template.MaterialTemplate(title='FlexBox Demo')
templ.sidebar.append('# Sidebar')

# doing this gets more and more sluggish as you add more FlexBox instances. For me it would crash the browser at about 6 or 7 
templ.main.append(pn.Column(*items, sizing_mode='stretch_width'))  

# doing this works great, no matter how many FlexBox instances you have
# templ.main.extend(pn.Column(*items, sizing_mode='stretch_width'))  

templ.servable()

Just a warning as you test this, when this crashed my browser tab it would also crash any other browser tabs that were running Python processes (i.e. all other panel applications and Jupyter lab tabs).

Note: the sidebar is not necessary to cause the issue, but closing it is the easiest way to trigger the issue.

@sdc50
Copy link
Contributor

sdc50 commented Dec 17, 2021

Just playing around with this now, but it looks like if there are nested Row and Column elements you have to call extend all the way down:

import random
import panel as pn
import param

rcolor = lambda: "#%06x" % random.randint(0, 0xFFFFFF)
rrange = lambda: range(random.randint(2, 10))

number_of_groups = 7

groups = [rrange() for i in range(number_of_groups)]

items = [pn.FlexBox(*[pn.pane.HTML(str(i), background=rcolor(), width=100, height=100) for i in g]) for g in groups]

main = pn.Column(sizing_mode='stretch_width')
row = pn.Row(align='center', sizing_mode='stretch_width')
col = pn.Column()
col.extend(items)
row.extend(col)
main.extend(row)


templ = pn.template.MaterialTemplate(title='FlexBox Demo')
templ.sidebar.append('# Sidebar')
templ.main.extend(main)

templ.servable()

Changing any of the extend calls to append will cause the error.

@sdc50
Copy link
Contributor

sdc50 commented Dec 22, 2021

if there are nested Row and Column elements you have to call extend all the way down

So I'm realizing that by calling extend I'm essentially just unpacking the contents of one container into the next, so there is no actual nesting going on. It seems that nested containers is what is causing the issue.

My goal is to have a set of FlexBox items centered in the page. The only way I can get this to work is by nesting them in Columns:

import random
import panel as pn
import param

rcolor = lambda: "#%06x" % random.randint(0, 0xFFFFFF)
rrange = lambda: range(random.randint(2, 10))

number_of_groups = 3

groups = [rrange() for i in range(number_of_groups)]

items = [pn.FlexBox(*[pn.pane.HTML(str(i), background=rcolor(), width=100, height=100) for i in g]) for g in groups]

main = pn.Column(
    pn.Spacer(height=1),  # The align='center' won't work unless I add this spacer. Not sure why that is.
    pn.Column(*items, align='center', max_width=1200, sizing_mode='stretch_width'), 
    sizing_mode='stretch_width'
)
main.show()

With only 3 groups it seems to work okay, except that it initializes with extra space between the FlexBoxes. Once I resize the page then the extra space goes away and it reacts as it should to page resize. But using any more groups than 3 will really bog things down (or crash the browser).

3 Groups:
flexbox_issue_3_groups

5 Groups:
flexbox_issue_5_groups

@philippjfr philippjfr modified the milestones: v0.12.x, v0.13.0 Jan 3, 2022
@philippjfr philippjfr modified the milestones: v0.13.0, next Mar 28, 2022
@philippjfr philippjfr modified the milestones: next, v1.0.0 Mar 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants