Angular 4 - Added non-passive event listener to a scroll-blocking 'mousewheel' event.
Asked Answered
G

2

6

In my Angular 4 Project I get the following warning when I click on a date-picker or a select-option menu, running it in Google Chrome:

[Violation] Added non-passive event listener to a scroll-blocking 'mousewheel' event. Consider marking event handler as 'passive' to make the page more responsive.

I already saw an issue here on stack-overflow but that one was about 'touchstart', not 'mousewheel'. I don't really know what Code-examples I could give you because I don't know where the warning comes from. Can anybody help me with this issue?

Goring answered 22/6, 2018 at 7:56 Comment(0)
E
3

What is a passive event?

Passive event listeners are a new feature in the DOM spec that enable developers to opt-in to better scroll performance by eliminating the need for scrolling to block on touch and wheel event listeners. Developers can annotate touch and wheel listeners with {passive: true} to indicate that they will never invoke preventDefault. This feature shipped in Chrome 51, Firefox 49 and landed in WebKit. Reference.

Chrome throws the warning ...

[Violation] Added non-passive event listener to a scroll-blocking 'wheel' event. Consider marking event handler as 'passive' to make the page more responsive.

...when you bind to mouse scroll events, to essentially warn that you may have inhibited scroll performance in your event or disabled default events by making a call to preventDefault().

Chrome also throws the error when you try and still call preventDefault() in a passive event.

Unable to preventDefault inside passive event listener invocation.

Firefox has a similar error for this, however does not seem to throw a warning like Chrome:

Ignoring ‘preventDefault()’ call on event of type ‘wheel’ from a listener registered as ‘passive’.

Warning showcase

Run the following snippet and view the Chrome console in Verbose mode.

// WILL throw violation
document.addEventListener("wheel", function(e) {
  e.preventDefault(); // prevents default browser functionality
});

// will NOT throw violation
document.addEventListener("wheel", function(e) {
  e.preventDefault(); // does nothing since the listener is passive
}, {
  passive: true
});

Resolving the issue

A similar SO post was made about the implications of this in javascript.

By marking a touch or wheel listener as passive, the developer is promising the handler won't call preventDefault() to disable scrolling. This frees the browser up to respond to scrolling immediately without waiting for JavaScript, thus ensuring a reliably smooth scrolling experience for the user.

Angular has not yet implemented a generic / ease of use solution for this and can be followed here.

However due to the fact that typescript is compiled to javascript, implementing the above snippet in typescript should still negate the violation.


Performance Impacts

The violation itself is not at all harmful to application performance, however the contents of your event function could be - and thus is why Chrome throws this warning. Note that this warning is only shown in Verbose console mode and will not be shown to general users.

As far as I am aware, there is no way to disable such warnings as they are generated by Chrome's interpretation of the code at run time.

Emmer answered 17/9, 2018 at 19:58 Comment(0)
S
2

Many libraries and frameworks add non-passive event listeners by default. Not much you can do about it.. Instead of waiting for a support I Would recommend using highly flexible and configurable passive-events-support package to debug and make event listeners passive without touching 3rd party source code.

First, after installing the package debug the touch and wheel event listeners and their parameters:

import { passiveSupport } from 'passive-events-support/src/utils'
passiveSupport({ debug: true })

This should console log all the event listeners

[Passive Events Support] Non-passive Event Listener
  element: div.some-element
  event: 'mousewheel'
  handler:
    fn: ƒ (e)
    fnArgument: 'e'
    fnContent: 'console.log(e)'
    fnPrevented: false
  arguments: false

Notice arguments parameter, if it is false, undefined or object without passive parameter inside, this event is what causes your browser to throw a warning and is impacting the scroll performance.

To fix it just use the package and logged information to make this exact event listener as passive:

import { passiveSupport } from 'passive-events-support/src/utils'
passiveSupport({
  debug: false,
  // add this one
  listeners: [
    {
      element: 'div.some-element',
      event: 'mousewheel'
    }
  ]
})

Be careful tho, event listeners that call preventDefault() should not be marked as passive, but to fix the warning should still have passive parameter with a value of false instead.

By default the package will check if it is prevented from the handler itself, but in case the event listener is prevented from the method called inside the handler, the package loses track of it. To force assign passive: false just pass prevented: true parameter to listeners item:

passiveSupport({
  //...
  listeners: [
    {
      element: 'div.some-element',
      event: 'mousewheel',
      prevented: true
    }
  ]
})

For me, this package fixed all the warnings cause by materialize and jquery. Hope it helps you too.

Shandishandie answered 22/1, 2022 at 9:58 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.