DT table not rendering when using HTML tag

I noticed that tables generated with the DT package fail to render in my HTML document when I apply a <details> HTML tag to the code chunk.

I'm a HTML novice and would appreciate it if someone explained why this happens. A workaround would be a welcome bonus.

Struggling to incorporate the HTML code in my post, so I've uploaded this screenshot instead.

Example

I wonder if this is not the same as in

and this is somehow browser related unfortunately.

Like something not well supported upstream in the Javascript library

One theory offered by a colleague is that the browser tries to load the data table before the DOM (?) is loaded. (I'm not sure about my terms here, this is tech hearsay.) Somehow Chrome gets around this, but Safari and Firefox do not.

My solution has been to:

  • Avoid data tables if possible (for simple ones, just use gt)
  • When necessary, explain how to use data tables and explain what to do when they don't appear, as follows:

Thank you for the insight.

Good to know the issue seems browser-specific.

I'll stop assuming the issue is related to my coding illiteracy, and I'll stick to kable tables whenever I need to save space in my markdown reports.

Also appreciate the reference to gt; I knew nothing about it, and the formatting options look great.

This is very odd, seems like an unintended interaction between DT and the <details> element, combined with a browser difference.

The DT tables aren't rendering within <details> because DT skips rendering if the widget's root element has zero width/height: DT/datatables.js at 9f84fb59fd99a3ca110bea7a9545ec32f2c4bf0f · rstudio/DT · GitHub. Since content within <details> is hidden by default, it won't have any width/height, so that'd explain why the tables don't render on initial page load.

But why do the tables render in Chrome, but not Firefox/Safari? From some googling, a recent Chrome 97 update apparently changed how <details> works. Content within collapsed <details> elements is now rendered (but hidden) on the page so find-in-page works for the hidden content. So in Chrome 97+, the widget element is actually rendered with a non-zero width although hidden, and the DT table gets rendered correctly. The blog post links to another page that says this <details> change is now part of the HTML spec, so Firefox/Safari may eventually work the same way.

For now, one workaround would be to expand the details by default using <details open>, if that's an option:

<details open>
<summary>DT table</summary>

```{r}
DT::datatable(mtcars)
```

</details>

Or resize the window to trigger DT's rerender-on-resize behavior, like @smithjd found.

Or a very terrible hack, add a JavaScript script that forces DT tables within collapsed <details> to rerender when you first expand the <details>. Here's an R Markdown snippet that seems to work, although I haven't tested this thoroughly:

```{js, echo=FALSE}
// Work around DT tables not rendering properly within <details> elements in Firefox/Safari
document.querySelectorAll('details').forEach(el => {
  el.addEventListener('toggle', () => {
    const tables = el.querySelectorAll('.datatables')
    tables.forEach(tbl => {
      if (tbl.querySelector('table')) {
        return
      }
      tbl.classList.remove('html-widget-static-bound')
      HTMLWidgets.staticRender(tbl)
    })
  }, { once: true })
})
```

Ultimately, the best place to address this issue is probably in the DT package though.

Thanks a lot @greg for this insights !

It seems like there is already one issue opens that needs yet to be addressed

I'm going with this even though it defeats the purpose of "details":

<details open><summary>Click here to hide or show this table</summary>
....
</details>

When the page renders the "details" panels are all showing and readers have to close them!

Consistency behavior across browsers seems like the most important thing at the moment.

Also, interesting that <summary> is a way to alter the text of <details> ... I hadn't seen that documented or used anywhere.

@cderv Oh good find, I should've searched within the DT repo instead, hah. But it was still interesting to dig into the Chrome change, and I might add a comment to that issue.

Yes please do!

I wonder if there could be a piece of JS that would be executed at the very last when everything is loaded, that would close all the details tags.
If I understand correctly the fact that they are opened by default allow for the DT to be correctly loaded. What happens if we close them after ?

Something like this (not tested)

const allDetails = document.querySelectorAll('details');
allDetails.forEach(details => {
    if (details.open) {
        details.open = false;
    }
});

worth a try probably, unless it has already be done and did not work and I missed this ! :slight_smile:

I'm not sure where I'd add that JS code in a distill context.

Just for grins, I tried:

<details close>

... but then the data table doesn't render in Firefox at all.

I think it is open is there, or it is not. There is no close

I don't think this is a distill only issue if this is related to the HTML widget library and browsers suppport.

Anyway, you could use the includes argument as any other R Markdown format, to include some HTML after the body (at last). THis could be a JS script tag that would execute a function at the very end when everything is loaded (one need to search on how to do that using JS).

I've added this to the _footer.html file on my distill site but non of the java script suggestions seem to work. Like I said below, I've ended up having all details tabs open when the page first loads. It's ugly but better than making some of the data unavailable to some site visitors.

1 Like

Thanks for trying my suggestion.