(this post is related to my other post Run code when sidebar is toggled visible/invisible but describes a different aspect - the other post is about detecting the toggle, this one is about reacting to it)
What I am trying to do
I am trying to ensure that a plotly plot always uses the full width available (but not more!), whether the sidebar is displayed or hidden.
Whether I can manage to get an event triggered automatically (see my other post) or have to do it via a button or a timer code, I want to ensure that the plotly graph fills the full area available.
How it behaves right now
My app initially loads with the sidebar expanded, and everything looks just fine:
However, if I now call the same redraw() method again, it does not readjust the width. It still looks exactly as in the screenshot above
Strangely, in my small toy app Anvil | Login
it does work - clicking the redraw button, which calls the plot’s redraw() method, does “shrink” the graph when it is clicked after the sidebar reappears.
But in my actual app (which I am happy to share…) with a much more complex plotly plot, it works for expanding after the sidebar disappears, but it doesn’t work for shrinking when it reappears…
What I would like to know
Generally speaking, what is the correct way to tell a plotly plot component to redraw/resize itself after a layout change (such as sidebar appearing/vanishing)?
If calling redraw() is the correct answer: What could be the reason for things working in my toy example, and for expanding in my real app, but not for shrinking in my real app?
hi @tobi_kellner, we think this should just happen automatically, so if you try your clone link now the plotly plot should redraw when you toggle the sidebar.
If you’re still having trouble with your main app, please let us know and we can look into it.
Hi @stucork, thanks for the reply!
It is now indeed working automatically in my clone linked app (did you change something??), but in my main app (where the plotly graph is a lot more complex) it resizes when the sidebar gets hidden (i.e. the plotly graph “grows”), but it doesn’t resize when the sidebar returns.
Here is a clone link to my main app, but it’s a complex app and not super well structured, so not expecting you to make sense of it. If you want to try it, just let it load the graph (takes up to 10 seconds in total) and then hide and reshow the sidebar - of course you are invited to try the other functionality, but it may crash on you constantly
Hmm, strange. I have just changed my main app to load exactly the same graph as in the clone linked app, and it still isn’t doing it correctly in the main app…
Wooow, @stucork , that actually fixed it. Thank you sooo much! Seriously, I am blown away by the level of support I am getting from people like you in this community.
There is still a tiny issue when my sidebar changes width (when different components inside are made hidden or visible), see below, but if that can’t be sorted then I can live with it (and I hope my users can, too :-))
Btw, is this something that should be passed on to the anvil-extras community?
Here’s the last remaining niggle (this is just FYI, it’s not a big deal):
When the sidebar is initially narrow and the plot resizes correctly…
For anyone adopting this:
The code above makes things look a bit wonky in the anvil editor/designer, but I found I can work around that by wrapping the code @stucork suggested in a simple if (!window.anvilInDesigner) { ... }
This is something I simply copy & pasted from elsewhere in standard-page.html so I have no deeper knowledge about how it works, but it seems to do what it says on the tin and ensures that everything looks pretty in the editor…
So now immediately under window.addEventListener('resize', addMarginToContent); I added
if (!window.anvilInDesigner) {
let adjustMarginTimeout;
const adjustMargin = new ResizeObserver(() => {
clearTimeout(adjustMarginTimeout);
adjustMarginTimeout = setTimeout(addMarginToContent, 50);
});
const leftNav = document.querySelector(".left-nav")
adjustMargin.observe(leftNav);
}
Here is another method I did, trying to stay on the python side, taking advantage of anvil.js import:
from anvil import js
from anvil.js.window import ResizeObserver
def handle_side_bar_toggle(self):
if self.observer is None:
self.observer = ResizeObserver(self.refresh_layout)
side_bar = js.window.document.querySelector('.sidebar')
self.observer.observe(side_bar)
def refresh_layout(self,*args,**event_args):
#Here I call a function to resize my object
self.board.layout()
def form_show(self, **event_args):
"""This method is called when the form is shown on the page"""
self.handle_side_bar_toggle()
def form_hide(self, **event_args):
"""This method is called when the form is removed from the page"""
if self.observer:
self.observer.disconnect()