[SOLVED] Datatables and Accessibility

I’m working on an app that will be accessed by users with visual impairments. I’m trying to make my app “accessible”, but I’ve found that my datatables fail accessibility checks for two reasons:

  1. The select column in my datatable does not have data in the header. This field is blank. I believe there is a way for me to add text to the header for the select column (e.g., “Select”), but I’m not sure how.

  2. The checkboxes in the select column do not have labels. Every form element is supposed to have a label as noted here: Form <input> elements must have labels Axe Rules | Deque University | Deque Systems


1 Like

I was able to add a header and then hide the header text by setting the font color to the same color as the background. I was also able to add titles to each of the checkboxes for row selection. These changes appear to satisfy the accessibility errors that were detected by Axe and WAVE, which are accessibility testing tools. I’ll probably have to manually edit the file after every upgrade, but I was able to resolve this by modifying the “…\site-packages\dash_table\async~table.js” file with the changes below…

("th",{key:"select",className:"expanded-row--empty-cell dash-select-header",style:{width:"30px",maxWidth:"30px",minWidth:"30px"}})

("th",{children:"Select",key:"select",className:"expanded-row--empty-cell dash-select-header",style:{width:"30px",maxWidth:"30px",minWidth:"30px",color:"#454545"}})

("td",{key:"select",className:"dash-select-cell",style:{width:"30px",maxWidth:"30px",minWidth:"30px",textAlign:"center"}},o.a.createElement("input",{type:"single"===n?"radio":"checkbox",style:{verticalAlign:"middle"},name:"row-select-".concat(e),checked:T.a(t,r),onChange:function(){var e="single"===n?[t]:yo(T.a(t),go([t]),mo(t))(r);a({selected_rows:e,selected_row_ids:d.a(function(e){return i[e].id},e)})}}))

("td",{key:"select",className:"dash-select-cell",style:{width:"30px",maxWidth:"30px",minWidth:"30px",textAlign:"center"}},o.a.createElement("input",{title:"checkbox",type:"single"===n?"radio":"checkbox",style:{verticalAlign:"middle"},name:"row-select-".concat(e),checked:T.a(t,r),onChange:function(){var e="single"===n?[t]:yo(T.a(t),go([t]),mo(t))(r);a({selected_rows:e,selected_row_ids:d.a(function(e){return i[e].id},e)})}}))

Thanks for this! We’ve raised an internal issue to make this more permanent or configurable in https://github.com/plotly/dash-table/issues/644.

Awesome! Much appreciated!

I’ll add an additional item that was flagged during a recent accessibility review. The datatable does not allow the user to navigate through the checkboxes using their keyboard (tabbing). Once you tab into the first checkbox, you’re effectively locked into a keyboard trap. At that point you cannot tab backwards or forwards. I’m currently working with Plotly support and some internal resources to find a solution or a workaround.


I found a workaround for the other accessibility issue that was preventing me from tabbing through the select checkboxes. I removed the following section of code from the async-table.js file.

n.handleKeyDown = function(e) {
	var t = n.props,
	r = t.setProps,
	o = t.is_focused;
	if (q.c.trace("handleKeyDown: ".concat(e.key)), a = e.keyCode, ![Y.CONTROL, Y.COMMAND_LEFT, Y.COMMAND_RIGHT, Y.COMMAND_FIREFOX].includes(a)) {
		var a, i = Q(e);
		i && e.keyCode === Y.V || e.keyCode === Y.C && i && !o || (e.keyCode !== Y.ESCAPE ? (!o && J(e.keyCode) && n.switchCell(e), o && !J(e.keyCode) || (e.keyCode !== Y.TAB && e.keyCode !== Y.ENTER ? e.keyCode !== Y.BACKSPACE && e.keyCode !== Y.DELETE || n.deleteCell(e) : n.switchCell(e))) : r({
			is_focused: !1

How to find this file on local machine and manipulate it? I can not find this

Hey @Ciamciaramcia, it depends on where you’ve installed Python. For me, my async-table.js file is located at the following path:


Thanks for ur answer i found it but it doesn’t help with my problem maybe u had similar?


@Ciamciaramcia - I’m not sure if this would fix your issue or not, but I removed the handleKeyDown function from my async-table.js file and that allowed users to tab through the table. The code, at least for the version I was using at the time, is copied into the comment I made above.