Everything works great as long as two tutorial steps don’t target the same button in a row. A later tutorial step can go back to a previous button, but only if there was a different step on a different button between them.
If you comment out line 17 in Form1 to eliminate the tutorial step on button_2, that gives us two consecutive steps on button_1. That generates the following error when you click Next on the first tutorial step:
: TypeError: Cannot read properties of null (reading 'trigger')
There’s no other stack information, just that.
It feels like a timing related issue again in Javascript, but I don’t know if it’s because I’ve hit a situation that the popover library doesn’t account for, or because I’m using it incorrectly.
The quick solution is to add a delay in your hide function.
def hide_step(self):
widget = self.notifications[self.tutorial_step]['widget']
widget.pop('destroy')
from time import sleep
sleep(.25)
It would be nice if you didn’t need that delay. So it’s something I’ll need to think about.
Or at the very least - improved docs/error handling.
(I’ll add an issue at anvil extras)
What we have is a race condition in the bootstrap architecture.
(Popovers use the underlying bootstrap implementation)
Explanation for what you’re seeing
Creating and destroying the popovers isn’t instant,
It also happens asynchronously but the python code runs synchronously,
you end up with a conflict between destroying a popover and showing a new one.
(Bootstrap thinks you’re trying to show a popover that’s has been destroyed).
By adding the sleep - we wait for the destroy to complete before then triggering the next show.
Not really. And - looking at the bootstrap docs, delay doesn’t apply to a manual trigger.
So the race condition is from manipulating the HTML elements. Creating and destroying HTML elements isn’t instant.