svelte: Plugin svelte: A11y: on:blur must be used instead of on:change, unless absolutely necessary and it causes no negative consequences for keyboard only or screen reader users.

I recently updated Svelte to latest version and this warning started to show up.

So I decided to try that out, change the on:change on some selects to on:blur, but they stopped working. It’s only after I click away from the select that the event gets triggered, simply selecting the option doesn’t do it.

I know I can simply ignore these, but I wanted to see if I can actually go ahead with this recommendation, maybe I’m doing something wrong. Thanks!

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 14
  • Comments: 16 (7 by maintainers)

Commits related to this issue

Most upvoted comments

I disabled it by putting a comment one line above the warning:

<!-- svelte-ignore a11y-no-onchange -->
<select  on:change={(e) => alert('hallo')}>
    <option>Item 1</option>
    <option>Item 2</option>
</select>

Edit: added select to example

Imo, this rule should be removed.

  1. The corresponding jsx-a11y rule was deprecated in Nov 2020.
  2. The WebAIM mailing thread linked above says that using onchange is fine in most cases. There shouldn’t be a warning for something that is usually okay, especially since the Svelte a11y warnings cannot be configured as easily as eslint.

The original reasoning behind this rule seemed to be that IE fired the change event when navigating between options with the arrow keys. From the linked article in the jsx-a11y docs:

The only problem is, when you use the keyboard to explore the options in a select menu (using cursor keys) it triggers the onchange event handler (in IE). So, if you have any actions that rely on that handler, they’ll probably be executed before the user has time to listen to all the options in the select menu. It’ll also mean they’ll probably only ever be able to access the first item.

This was from 2004 and seems to be out of date now. I wrote a quick CodePen to see when the change event is fired for a <select> and tested in IE11, Chrome, and Firefox. In all browsers tested, tabbing to the select, opening the menu with Space, and using the arrow keys to navigate between different items did not fire a change event. A change event was only fired when an item was selected with Enter or if the arrow keys were used to select an option without opening the menu.

While older versions of IE may have made this necessary, I don’t think it’s reasonable to enforce a warning for all developers that only applies to a very small subset of people supporting IE < 11.

tl;dr the jsx-a11y this was based on is now deprecated. The rationale is many years old now and not applicable to most use cases when using a modern browser or IE11.

Something I just realized while interacting with this warning — wouldn’t this imply that bind:value is also inadvertently breaking the a11y rule? I was helping someone “fix” this warning and our answer was to swap to using bind:value instead (which was the better choice anyway/more Svelte-y). But it did get me thinking about what it was doing behind the scenes and sure enough — it’s a change listener!

image

There’s a webaim.org mailing thread that discusses this issue: https://webaim.org/discussion/mail_thread?thread=8036

Quoting the reply:

In most cases [using onChange] is actually ok. There are 3 scenarios where this is absolutely a problem (and defect under WCAG 3.2.2)

  1. If the onchange event automatically moves focus to somewhere else on the page. This is a problem, because when you are in a dropdown and press the arrow key the onchange event is triggered. Then your focus may land somewhere else. If you are a keyboard only user and wanted to select the 6th option in the dropdown it could take you a long time if you have to refocus the dropdown for every arrow down press.
  2. If the onchange event triggers navigating to a different page or opening of another user agent (like auto playing a video or displaying a PDF file) … I have never seen this except in theoretical scenarios , but it could be coded that way.
  3. If the onchange event changes content that is located, in content order, before the dropdown. This could be remediated in some cases using an ARIA live region, but it is usually just a bad idea. If your interaction with a control changes the content, the change should occur after the control, it is commonsensical.

Thanks, this warning is way over the top. It’s absolutely untrue that it doesn’t change anything for desktop.

How do I disable this warning… on:blur does not work for my use case. It is annoying to see on Visual Studio Code.

How do I disable this warning… on:blur does not work for my use case. It is annoying to see on Visual Studio Code.

Edit your rollup.config.js like this. This will give you the opportunity to add more warnings later on.

const onwarn = (warning, onwarn) => {
	const isCircularWarning = warning.code === 'CIRCULAR_DEPENDENCY' && /[/\\]@sapper[/\\]/.test(warning.message); // only for @sapper
	const isOnBlurInsteadOfOnChangeWarning = warning.code === 'PLUGIN_WARNING' && warning.pluginCode && warning.pluginCode === 'a11y-no-onchange';

	return isCircularWarning
		|| isOnBlurInsteadOfOnChangeWarning
		|| onwarn(warning);
}


export default {
	client: {
          ...
          onwarn,
        },
       server: {
         ..., 
         onwarn,
       }
}

Ah, I see. Here’s the official (as far as I’ve been able to find) rule that the Svelte one was adapted from: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-onchange.md.

Really, I think there’s frustratingly little guidance on this rule. It’s a big change from what most web developers currently do and the description of the rule is extremely vague on when it’s ok to use onchange or not if you aren’t already an accessibility expert. The link I posted above has two article links, one of which is dead and the other which is 15 years old: http://www.themaninblue.com/writing/perspective/2004/10/19/

That article is basically is making the case against doing what I mentioned in the last paragraph of my previous comment. This was common back in 2004 when select menus were often used as a kind of simple dropdown navigation, and selecting an option would trigger a page change. But I think that kind of behavior is pretty rare today though.

So I would just sum this one up as “make sure your select’s on:change handler is friendly to keyboard users” and keep on using on:change. I think that’s what I’m going to do.

How would you ignore this warning if you are running Webpack?

My understanding is that’s the behavior change you described is actually the entire point of using on:blur as opposed to on:change.

If the user is accessing the select control with a keyboard, then as they go through the options in the select menu, on:change will be fired for each one. But if you use blur, then you only look at the value of the select once it has closed, so you aren’t taking action against intermediate values that the user didn’t want to select.

I’m not an a11y expert, but I think so long as you don’t do anything unreasonable in your change handler, like making large alterations to the page layout, triggering a bunch of network queries, or anything that might cause the select menu to close, then you’re just fine continuing to use on:change.