shiny.quetzio is a system for easy creation of questionnaires using various Shiny input widgets. As the source for their render it can use a YAML config file, googlesheet from the web or list/data.frame.
Rendering and questionnaire reactivity is completely handled by shiny modules, so it is easy to include multiple independent questionnaires in your ShinyApp while keeping the code clean!
To learn more:
You can install the development version of shiny.quetzio from GitHub with:
# install.packages("devtools")
devtools::install_github("StatisMike/shiny.quetzio")
At the current stage of development, survey generation is handled
exclusively by two R6
classes to be initialized in server portion of
your App. Additionally it provides corresponding functions to bind the
UI elements and some helper functions.
Quetzio
class creates single questionnaire (you can initialize it
with Quetzio_create()
function). Use Quetzio_UI()
to bind the UI
of the questionnaire. Questionnaires currently handle these type of
inputs:
textInput
numericInput
selectizeInput
radioButtons
likertRadioButtons
(custom input type - for more information
read the corresponding subsection of “Other features” section)QuetzioLink
class links multiple Quetzio
objects (you can create
it with QuetzioLink_create()
function). Use QuetzioLink_UI()
to
bind the connected UI.
Helper generic functions that work with both Quetzio
and
QuetzioLink
objects:
Quetzio_label_update()
Quetzio_value_update()
Quetzio_get_df()
Choosing
numericInput
for item type, the object that will be generated is actually custom input widget:numInput
. It allows no initial value and placeholder text.
It’s usage is very straightforward:
Quetzio
object in your shinyApp server code,
and Quetzio_UI
in your ui:ui <- fluidPage(
Quetzio_UI("yaml_module"),
Quetzio_UI("gsheet_module")
)
server <- function(input, output, session) {
# YAML generated survey with output automatically saved to googlesheets
yaml_quetzio <- Quetzio_create(
source_method = "yaml",
source_yaml = "some_yaml",
output_gsheet_id = "googlesheet_id",
output_gsheet_sheetname = "sheet_name_with_questions",
module_id = "yaml_module"
)
# survey generated from googlesheet source, with output automatically saved to
# googlesheets
gsheet_quetzio <- Quetzio_create(
source_method = "gsheet",
source_gsheet_id = "googlesheet_id",
source_gsheet_sheetname = "sheet_name_with_questions",
# you don't need to specify another googlesheet file to save answers
# If you don't specify it, the class assumes it is the same as source one
output_gsheet_id = "another_googlesheet_id",
output_gsheet_sheetname = "sheet_name_with_answers",
module_id = "gsheet_module"
)
}
# trigger some action after the questionnaire is completed
observe({
req(yaml_quetzio$is_done())
showModal(
modalDialog("You're done!")
)
})
# catch the answers provided to the questionnaire
output$gsheet_answers <- renderPrint(
gsheet_quetzio$answers()
)
QuetzioLink
R6 class:ui <- fluidPage(
QuetzioLink_UI("modules_link")
)
server <- function(input, output, session) {
# Linked questionnaires - one generated from yaml, second from googlesheets.
# Their output won't be automatically saved to googlesheets in this example
# (though it is possible to set - their internal reactivity is independent
# to the quetzio_link in that regard)
quetzio_link <- QuetzioLink_create(
yaml_quetzio = Quetzio_create(
source_method = "yaml",
source_yaml = "some_yaml",
module_id = "yaml_module"
),
gsheet_quetzio = Quetzio_create(
source_method = "gsheet",
source_gsheet_id = "googlesheet_id",
source_gsheet_sheetname = "sheet_name_with_questions",
module_id = "gsheet_module"
),
link_id = "modules_link"
)
# and you can also trigger things based on the completion rate
# trigger some action after the link is 50% completed and after completion
# of both questionnaires
observe({
if (quetzio_link$completion() == 0.5) {
showModal(
modalDialog("You're half done!")
)
} else if (quetzio_link$completion() == 1) {
showModal(
modalDialog("You're completely done!")
)
}
})
# catch the answers provided to the questionnaire
output$all_answers <- renderPrint(
quetzio_link$answers()
)
}
You can configure your survey widely using many of the features native to the used Shiny inputs.
For every input you can specify:
Bold ones are mandatory for every input
| parameter | textInput | numericInput | selectizeInput | radioButtons | likertRadioButtons | |:------------:|:---------:|:------------:|:--------------:|:------------:|:------------------:| | placeholder | x | x | x | | x | | regex | x | | | | | | value | | x | | | | | min | | x | | | | | max | | x | | | | | step | | x | | | | | choices | | | x | x | | | choiceValues | | | x | x | x | | choiceNames | | | x | x | x | | maxItems | | | x | | | | create | | | x | | | | maxOptions | | | x | | | | selected | | | x | x | x | | inline | | | | x | |
Parameters with bolded x are mandatory. You can specify either choices or both choiceValues and choiceNames for
selectizeInput
andradioButtons
.
For more information about these, check vignettes and documentation.
reactive
expression valuelikertRadioButtons
is new input type created to accomodate the lack of
input that is meeting all requirements to create good looking and
functional input for questions with Likert-like scoring scale
supports no initial selected value - which is essential to make sure that the questionee selected the value themmselves. It is based on radio HTML input.
displays semantic meaning of each value, or just min and max
sends the selected value to the server in its numeric form
UI presentation:
r
likertRadioButtons(
inputId = "with_ind", label = "With indicator",
choiceValues = c(-2:2),
choiceNames = c("Very bad", "Slightly bad", "Not bad or good",
"Slighty good", "Very good")
r
likertRadioButtons(
inputId = "wo_ind", label = "Without indicator",
choiceValues = 1:7, choiceNames = c("Not much", "Many"))
Currently the usability of
likertRadioButtons
is limited - there is no way to update the value or other elements after rendering. There is no function likeupdateLikertRadioButtons
presently created. It is planned to be implemented sometime in the future. For the time being, if you plan to use it outside ofQuetzio
and update its contents reactively, it is advised to do it usingrenderUI
.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.