<- 5 x
I am writing a (still very much unfinished) psychometrics book with suggested exercises using R. I wanted to provide solutions to the questions, but I wanted to hide the answers until the reader clicks them.
An easy way to create collapsible content is with html’s <details>
tag. For example:
Create a variable `x`, and assign it a value of 5.
<details>
<summary>Suggested Solution</summary>
```{r}
x <- 5
```
</details>
Create a variable x
, and assign it a value of 5.
Suggested Solution
However, I did not want to worry about all the <details>
every time I wrote a question. To automate this process, I used two knitr hooks: a chunk hook and an option hook.
Chunk hooks are for customizing the output of a chunk.
Here I create a new chunk hook that is run before and after the chunk. When it is run before the chunk, it adds the <details>
and <summary>
tags. After the chunk, it closes the <details>
tag.
# Add the details tag before running the chunk
# and close the tag after running the chunk.
::knit_hooks$set(
knitrsolutionsetter = function(before,options) {
if (before) {
"\n\n<details><summary>Suggested Solution</summary>\n\n"
else {
}
"\n\n</details>\n\n"
} })
If all we needed to do was to enclose the output into a <details>
tag, then just the solutionsetter
hook would be needed. However, I also wanted to set echo=TRUE
so that the output would be visible even if the default for echo
was FALSE
.
Option hooks are great for when you have a kind of chunk you will use often, and it requires setting many chunk options at once (e.g., a plot variant with different dimensions than your default plot has).
Here I create a new option hook called solution
. It sets the current chunk’s echo
option to TRUE
and also triggers the new solutionsetter
code chunk below. The updated options
list needs to be returned explicitly, or the hook will not work.
::opts_hooks$set(solution = function(options) {
knitr$echo <- TRUE
options$solutionsetter <- TRUE
optionsreturn(options)
})
Now all need to do is to set my chunk option to solution = TRUE
and the output will be collapsible:
Create a variable `x`, and assign it a value of 5.
```{r, solution = TRUE}
x <- 5 ```
Create a variable x
, and assign it a value of 5.
Suggested Solution
<- 5 x
The details package
If you want a function to enclose the output of a chunk or inline code in <details>
tags, use the details package by Jonathan Sidi. For example, an inline chunk like this:
`r details::details("Answer", summary = "Question")`
Will output like so:
Question
Answer
The package has many other uses, which are explained in the package’s vignettes.
Citation
@misc{schneider2023,
author = {Schneider, W. Joel},
title = {Creating Collapsible Output with Knitr Chunk Hooks},
date = {2023-06-30},
url = {https://wjschne.github.io/posts/creating-collapsible-output-with-knitr-chunk-hooks/},
langid = {en}
}