bootstrap icon indicating copy to clipboard operation
bootstrap copied to clipboard

function _isWithActiveTrigger in tooltip.js is causing an uncaught error

Open njmkramer opened this issue 3 years ago • 39 comments
trafficstars

Prerequisites

Describe the issue

Uncaught TypeError: Cannot convert undefined or null to object
at Function.values ()
at Popover._isWithActiveTrigger (tooltip.js:549:19)
at complete (tooltip.js:279:16)
at execute (index.js:254:5)
at HTMLDivElement.handler (index.js:276:5)
at triggerTransitionEnd (index.js:98:11)
at index.js:282:7

This happens when multiple elements have a popover or a popover is attached to a new element and fast switching hover on elements.

Reduced test cases

suggestion:

_isWithActiveTrigger() {
if(typeof this._activeTrigger == 'undefined' || this._activeTrigger === null){
return false;
}
return Object.values(this._activeTrigger).includes(true)
}

What operating system(s) are you seeing the problem on?

Windows

What browser(s) are you seeing the problem on?

Chrome

What version of Bootstrap are you using?

v5.2.2

njmkramer avatar Nov 11 '22 09:11 njmkramer

Hello @njmkramer. Bug reports must include a live demo of the issue. Per our contributing guidelines, please create a reduced test case on CodePen or StackBlitz and report back with your link, Bootstrap version, and specific browser and Operating System details.

github-actions[bot] avatar Nov 11 '22 23:11 github-actions[bot]

Reduced test:

https://js-cq37dw.stackblitz.io/

Focus as fast as you can different inputs and hover at the same time, enter a value, at some point the error will occur. Tested on Chrome version: 107.0.5304.107 Bootstrap 5.2.2 @popperjs/core 2.11.6

njmkramer avatar Nov 14 '22 12:11 njmkramer

Hi @julien-deramond, see my previous comment for reduced test/live demo.

njmkramer avatar Nov 16 '22 09:11 njmkramer

Hi @julien-deramond any progress on this issue?

best regards

njmkramer avatar Dec 05 '22 10:12 njmkramer

Running into this as well..

hyphen81 avatar Jan 15 '23 15:01 hyphen81

As much as I 've tested till now, I cannot replicate the issue :confused:

GeoSot avatar Jan 16 '23 09:01 GeoSot

_isWithActiveTrigger

fix: if (this!== null) { if ( typeof this._activeTrigger != 'undefined' && typeof this._activeTrigger.hover == 'undefined' ) { this._activeTrigger.hover = false; } }

njmkramer avatar Jan 16 '23 15:01 njmkramer

fix: if (this!== null) { if ( typeof this._activeTrigger != 'undefined' && typeof this._activeTrigger.hover == 'undefined' ) { this._activeTrigger.hover = false; } }

sorry to disappoint you, but this is not a fix, it is just a super defensive approach to save the situation of something really wrong (Tooltip is not initialized at all)

I am here to help, but I will need your cooperation, in order to replicate the issue. I have tried to many times this example, without results.

Please, create a codepen example to be able to follow your code, and try to explain me in simple bullets (steps) how to replicate.

GeoSot avatar Jan 16 '23 15:01 GeoSot

Thanxs for your reply, I wil updated the live test in the coming days

njmkramer avatar Jan 17 '23 09:01 njmkramer

Explaination:

1: from top to bottom: focus each input -> it will turn red and have a hover 'enter a value'

2: from top to bottom: focus and type a value -> hover will disappear or the error will occur

3: from top to bottom: clear the input

4: repeat 1, 2 and 3 until the error comes up and it will

Sometimes the error came up very quickly, other times I had to repeat the 4 steps serveral times, as fast as I could, to trigger the error to come up.

I hope this helps you to see the problem

njmkramer avatar Jan 17 '23 15:01 njmkramer

can you please do it in a code pen in order to be able to see your code ? ( or provide an open project url for stackblitz)

GeoSot avatar Jan 18 '23 23:01 GeoSot

I'm seeing the same problem in Sentry from my Users, but I can also not reproduce it using the StackBlitz from @njmkramer, neither in Firefox (where I'm getting the User reports from) nor in Safari.

theomega avatar Jan 19 '23 09:01 theomega

url to the code:

https://stackblitz.com/edit/js-cq37dw?file=index.js

njmkramer avatar Jan 19 '23 13:01 njmkramer

https://user-images.githubusercontent.com/98040092/214544689-ebedb56b-237f-4cb2-8e3a-23e8c0ad468a.mp4

screenshot of error occuring

njmkramer avatar Jan 25 '23 10:01 njmkramer

@GeoSot see screenshot where the error occurs. Best regards Norbert

njmkramer avatar Jan 25 '23 10:01 njmkramer

I'm experiencing the very same issue when using Bootstrap with Blazor and trying to navigate to another route (removes the elements from DOM) when the tooltip is still displayed: 2023-02-01_17-48-23

The Blazor code is as simple as follows:

@inject NavigationManager NavigationManager

<HxButton Text="Navigate home"
	Tooltip="Navigate"
	Color="ThemeColor.Primary"
	OnClick="@(() => NavigationManager.NavigateTo(""))" />

HxButton is a component from a Blazor library wrapping Bootstrap: https://havit.blazor.eu/

For now, I'm not trying to give you a regular repro, just adding some additional info to the issue.

BTW: My original intention was to reproduce this issue (https://github.com/havit/Havit.Blazor/issues/457): image ...but when I recreated the original scenario, the _activeTrigger error appeared instead.

hakenr avatar Feb 01 '23 16:02 hakenr

I am also experiencing this issue in [email protected] even though my setup is a bit different than the one described by @njmkramer

I am using the Tooltips class in a [email protected] custom directive that automatically instantiates tooltips on elements with the directive.

It is also really difficult to replicate the error in my case but from the experimenting I've done, at the time of error this is completely empty:

{
    "_element": null,
    "_config": null,
    "_isEnabled": null,
    "_timeout": null,
    "_isHovered": false,
    "_activeTrigger": null,
    "_popper": null,
    "_templateFactory": null,
    "_newContent": null,
    "tip": null,
    "_hideModalHandler": null
}

So this makes me think that in some way (that I still haven't managed to figure out):

  1. the element which is causing the error has its Tooltip instance disposed of via the dispose() function (hence all the null properties)
Screenshot 2023-02-28 at 13 37 54

from bootstrap.bundle.js:809

  1. but the element still has the mouseover Events attached to it even after the instance is disposed of (at least the mouseleave, which triggers the hide() function that causes _isHovered to be false unlike all the other properties that are null)

So I'm guessing the problem resides either in the Events management after the Tooltip instance is disposed of, or when it's re-instantiated on the same element after the previous instance was disposed of.

Andream98 avatar Feb 28 '23 12:02 Andream98

simple live demo: https://codepen.io/alchimik-irk/pen/abapgLZ

alchimik avatar Mar 01 '23 08:03 alchimik

simple live demo: https://codepen.io/alchimik-irk/pen/abapgLZ

My friend, this is a wrong approach, as you are trying to dispose the tooltip instantly, not giving the proper time for hide process to get finished

the right approach on this is

setTimeout( () =>{  
  tooltipEl.addEventListener('hidden.bs.tooltip', ()=> { tooltipBs.dispose() } )
  tooltipBs.hide(); 
}, 2000);

ref: #38018

GeoSot avatar Mar 01 '23 11:03 GeoSot

That might be a wrong usage of the class but it is useful to reproduce the error consistently.

In my case I'm using the dispose() method (as the documentation states here) to hide the tooltip and remove the instance from an item, but this is sometimes generating the error.

Here's my code: Screenshot 2023-03-01 at 12 44 58

I'm guessing that when the dispose() method is called, another call to hide() gets executed at the same time maybe by the mouseleave event.

I think a failsafe in the dispose() method is required to prevent these edge cases.

Andream98 avatar Mar 01 '23 11:03 Andream98

Update: In my case the error occurs frequently when an input already has a popover with an error message, by script a new error message comes in. The existing popover must be disposed before the new message can be shown. If the mouseover/mouseleave is triggered during that disposing and adding the new popover the error occurs. Even if I set a timeout of 2 sec. between disposing and adding

1: start disposing

2: doing mouseover and mouseleave over the input with a popover

error occurs: tooltip.js:536 Uncaught TypeError: Cannot convert undefined or null to object at Function.values () at Popover._isWithActiveTrigger (tooltip.js:536:19) at complete (tooltip.js:268:16) at execute (index.js:254:5) at HTMLDivElement.handler (index.js:276:5) at triggerTransitionEnd (index.js:98:11) at index.js:282:7 _isWithActiveTrigger @ tooltip.js:536 complete @ tooltip.js:268 execute @ index.js:254 handler @ index.js:276 triggerTransitionEnd @ index.js:98 (anonymous) @ index.js:282 setTimeout (async) executeAfterTransition @ index.js:280 _queueCallback @ base-component.js:49 show @ tooltip.js:238 (anonymous) @ tooltip.js:511 setTimeout (async) _setTimeout @ tooltip.js:532 _enter @ tooltip.js:509 (anonymous) @ tooltip.js:465 handler @ event-handler.js:98

(2 sec. passed) 3: add new popover

I hope this helps in finding a solution for this nasty error.

njmkramer avatar Mar 10 '23 17:03 njmkramer

sreencast of error occuring during disposing and mouseover/mouseleave.

https://user-images.githubusercontent.com/98040092/224481302-e55a3e92-e4de-4327-9673-3bc148f380d7.mp4

njmkramer avatar Mar 11 '23 11:03 njmkramer

#36080 - same problem, with a solution, not merged

alchimik avatar Mar 12 '23 16:03 alchimik

same here

MarkGorissen avatar Mar 22 '23 07:03 MarkGorissen

Same issue here. My users also encounter this error (I have a logging system that logs user errors on the frontend), but I have never achieved to reproduce it on my side. Below are the user agents of my users devices who encountered this same issue:

  • Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 = Chrome 112 on Windows 10
  • Mozilla/5.0 (iPhone; CPU iPhone OS 16_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/112.0.5615.167 Mobile/15E148 Safari/604.1 = Chrome 112 on iOS 16.3 (Apple iPhone)

Does anyone have any leads? Thanks

Rezyan avatar Apr 30 '23 04:04 Rezyan

I ran into the same issue, it occur when I call tooltip.dispose() in unmount of component in React, while I change it to call tooltip.hide(), it is ok and also meet my demand.

mahui-cn avatar May 14 '23 15:05 mahui-cn

@GeoSot Hi, when can i or we, expect a solution for this issue. The uncaught error is a real pain in the a**. Users have to reload the page because of this. Thanxs in advance

njmkramer avatar May 23 '23 06:05 njmkramer

I managed to find a workaround;

var popover = Popover.getInstance(obj);
if (popover !== null && typeof popover.dispose === 'function') {
  popover.disable();
  popover.hide();
  setTimeout(function () {
    popover.dispose();
  }, 300);
}

njmkramer avatar May 23 '23 08:05 njmkramer

I ran into this error and because of the comments in this issue I was able to resolve it.

In my scenario I wanted to change the title/position after the tooltip was initialised. I did this by disposing the tooltip and immediately re-initialising the tooltip with the latest values. This works, however when the tooltip was shown and the title/position updated, it resulted in this error.

I found that you can use lambdas instead to always get the latest values, like so:

 new Tooltip(this.element, {
  "title": () => this.title,
  "placement": () => this.placement
});

Now I only dispose the tooltip when the element gets destroyed.

Update 7 September 2023: Still getting the issue. The reproduction is actually straightforward: call dispose when the tooltip is visible, then the error will be thrown; unless you dispose after the hidden event triggered.

TomONeill avatar Jul 26 '23 09:07 TomONeill

Here's a workaround:

const disposePopover = popover => {
  setTimeout(() => popover?.dispose(), 100)
}

kblicharski avatar Jul 31 '23 16:07 kblicharski