Popovers - implementing triggering a popover on the same element

Hi @stucork, I’m not sure if what I’m seeing is a bug in popovers, another timing related Javascript thing, or just something I’m doing wrong.

I’m using popovers for tutorial steps in an app. Here’s a sample app that shows the concept: Tutorial Tests

And the clone for it: Anvil | Login

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.

1 Like

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.

2 Likes

Would it help (is it possible) to change the delay property from 100 to 1, so at least the delay could be shorter?

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.

(edited explanation above)

1 Like

This is probably an atypical use case for the popups, and the sleep works great as a workaround. Thanks for the workaround and the explanation!

1 Like

I think I have a fix - It should be ready for the next anvil-extras release.
Once it’s released you should be able to remove the time delays in code.

2 Likes