{"id":14066112,"url":"https://github.com/StatisMike/shiny.quetzio","last_synced_at":"2025-07-29T22:30:54.020Z","repository":{"id":42654555,"uuid":"430048798","full_name":"StatisMike/shiny.quetzio","owner":"StatisMike","description":"Create a survey in a ShinyApp","archived":false,"fork":false,"pushed_at":"2022-03-29T19:49:20.000Z","size":4570,"stargazers_count":3,"open_issues_count":4,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-30T19:41:18.656Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://statismike.github.io/shiny.quetzio/","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/StatisMike.png","metadata":{"files":{"readme":"README.Rmd","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-11-20T08:24:44.000Z","updated_at":"2024-07-05T18:12:41.000Z","dependencies_parsed_at":"2022-08-19T23:50:39.287Z","dependency_job_id":null,"html_url":"https://github.com/StatisMike/shiny.quetzio","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StatisMike%2Fshiny.quetzio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StatisMike%2Fshiny.quetzio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StatisMike%2Fshiny.quetzio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/StatisMike%2Fshiny.quetzio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/StatisMike","download_url":"https://codeload.github.com/StatisMike/shiny.quetzio/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228052698,"owners_count":17862106,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-13T07:04:56.631Z","updated_at":"2024-12-04T05:31:23.682Z","avatar_url":"https://github.com/StatisMike.png","language":"R","funding_links":[],"categories":["R"],"sub_categories":[],"readme":"---\noutput: github_document\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, include = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"man/figures/\",\n  out.width = \"100%\"\n)\n```\n\n# shiny.quetzio \u003cimg src='man/figures/logo.png' align=\"right\" height=\"200\" title = \"Created by Sandra Folwarczny\"/\u003e\n\n\u003c!-- badges: start --\u003e\n[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental)\n[![Codecov test coverage](https://codecov.io/gh/StatisMike/shiny.quetzio/branch/main/graph/badge.svg)](https://app.codecov.io/gh/StatisMike/shiny.quetzio?branch=main)\n\u003c!-- badges: end --\u003e\n\n## Overview\n\n**shiny.quetzio** is a system for easy creation of questionnaires using various\nShiny input widgets. As the source for their render it can use a YAML config file,\n*googlesheet* from the web or list/data.frame.\n\nRendering and questionnaire reactivity is completely handled by shiny modules,\nso it is easy to include multiple independent questionnaires in your *ShinyApp*\nwhile keeping the code clean! \n\nTo learn more:\n\n- Preview the `pkgdown` generated website [here](https://statismike.github.io/shiny.quetzio/){target=\"_blank\"}\n- View the interactive demo hosted on shinyapps [here](https://statismik.shinyapps.io/quetzio-demo/){target=\"_blank\"}\n\n## Installation\n\nYou can install the development version of **shiny.quetzio** from *GitHub* with:\n\n``` r\n# install.packages(\"devtools\")\ndevtools::install_github(\"StatisMike/shiny.quetzio\")\n```\n## Main features\n\nAt the current stage of development, survey generation is\nhandled exclusively by two `R6` classes to be initialized in *server* portion\nof your App. Additionally it provides corresponding functions \nto bind the UI elements and some helper functions.\n\n* `Quetzio` class creates single questionnaire (you can initialize it with \n`Quetzio_create()` function). Use `Quetzio_UI()` to bind the UI of the \nquestionnaire. Questionnaires currently handle these type of inputs:\n  - `textInput`\n  - `numericInput`\n  - `selectizeInput`\n  - `radioButtons`\n  - `likertRadioButtons` (custom input type - for more information read the\n  corresponding subsection of \"Other features\" section)\n\n* `QuetzioLink` class links multiple `Quetzio` objects (you can create it with \n`QuetzioLink_create()` function). Use `QuetzioLink_UI()` to bind the connected UI.\n\n* Helper generic functions that work with both `Quetzio` and `QuetzioLink`\nobjects:\n  - `Quetzio_label_update()`\n  - `Quetzio_value_update()`\n  - `Quetzio_get_df()`\n\n\u003eChoosing `numericInput` for item type, the object that will be generated is\nactually custom input widget: `numInput`. It allows no initial value and \nplaceholder text.\n\n### In-App usage\n\nIt's usage is very straightforward:\n\n1. Simply add a `Quetzio` object in your *shinyApp* **server** code, and `Quetzio_UI`\nin your **ui**:\n\n```{r, eval = F}\nui \u003c- fluidPage(\n  Quetzio_UI(\"yaml_module\"),\n  Quetzio_UI(\"gsheet_module\")\n)\n\nserver \u003c- function(input, output, session) {\n\n# YAML generated survey with output automatically saved to googlesheets\n\nyaml_quetzio \u003c- Quetzio_create(\n  source_method = \"yaml\",\n  source_yaml = \"some_yaml\",\n  output_gsheet_id = \"googlesheet_id\",\n  output_gsheet_sheetname = \"sheet_name_with_questions\",\n  module_id = \"yaml_module\"\n)\n\n# survey generated from googlesheet source, with output automatically saved to\n# googlesheets\n\ngsheet_quetzio \u003c- Quetzio_create(\n  source_method = \"gsheet\",\n  source_gsheet_id = \"googlesheet_id\",\n  source_gsheet_sheetname = \"sheet_name_with_questions\",\n  # you don't need to specify another googlesheet file to save answers\n  # If you don't specify it, the class assumes it is the same as source one\n  output_gsheet_id = \"another_googlesheet_id\",\n  output_gsheet_sheetname = \"sheet_name_with_answers\",\n  module_id = \"gsheet_module\"\n)\n\n}\n```\n\n2. Additionally, your ShinyApp can monitor the questionnaire status and react fully customizable!\n\n```{r, eval = F}\n  \n# trigger some action after the questionnaire is completed\n  observe({\n    req(yaml_quetzio$is_done())\n    showModal(\n      modalDialog(\"You're done!\")\n    )\n  })\n\n# catch the answers provided to the questionnaire\n  output$gsheet_answers \u003c- renderPrint(\n    gsheet_quetzio$answers()\n  )\n\n```\n\n3. There is also an option to link your questionnaires in a way that they\nwill appear one after another with `QuetzioLink` R6 class:\n\n```{r, eval = F}\nui \u003c- fluidPage(\n  QuetzioLink_UI(\"modules_link\")\n)\n\nserver \u003c- function(input, output, session) {\n\n# Linked questionnaires - one generated from yaml, second from googlesheets. \n# Their output won't be automatically saved to googlesheets in this example\n# (though it is possible to set - their internal reactivity is independent\n# to the quetzio_link in that regard)\n\n  quetzio_link \u003c- QuetzioLink_create(\n    yaml_quetzio = Quetzio_create(\n      source_method = \"yaml\",\n      source_yaml = \"some_yaml\",\n      module_id = \"yaml_module\"\n    ),\n    gsheet_quetzio = Quetzio_create(\n      source_method = \"gsheet\",\n      source_gsheet_id = \"googlesheet_id\",\n      source_gsheet_sheetname = \"sheet_name_with_questions\",\n      module_id = \"gsheet_module\"\n    ),\n    link_id = \"modules_link\"\n  )\n\n  # and you can also trigger things based on the completion rate\n  \n  # trigger some action after the link is 50% completed and after completion\n  # of both questionnaires\n  observe({\n    if (quetzio_link$completion() == 0.5) {\n      showModal(\n        modalDialog(\"You're half done!\")\n      )\n    } else if (quetzio_link$completion() == 1) {\n      showModal(\n        modalDialog(\"You're completely done!\")\n      )\n    }\n  })\n\n# catch the answers provided to the questionnaire\n  output$all_answers \u003c- renderPrint(\n    quetzio_link$answers()\n  )\n\n}\n```\n\n\n### Survey configuration\n\nYou can configure your survey widely using many of the features native to the\nused *Shiny* inputs. \n\n#### Universal parameters:\n\nFor every input you can specify:\n\n- **inputId**\n- **type**\n- **label**\n- mandatory: (true/false) if the input must be filled\n- width: the same as in regular input specification. If not provided, defaults\nto 500px\n\n\u003e *Bold* ones are mandatory for every input\n\n#### Type-specific parameters:\n\n\n|    parameter   |  textInput |numericInput|selectizeInput|radioButtons|likertRadioButtons|\n|    :----:      |   :----:   |   :----:   |    :----:    |   :----:   |      :----:      |\n|placeholder     |      x     |     x      |       x      |            |        x         |\n|regex           |      x     |            |              |            |                  |\n|value           |            |     x      |              |            |                  |\n|min             |            |     x      |              |            |                  |\n|max             |            |     x      |              |            |                  |\n|step            |            |     x      |              |            |                  |\n|choices         |            |            |     **x**    |    **x**   |                  |\n|choiceValues    |            |            |     **x**    |    **x**   |      **x**       |\n|choiceNames     |            |            |     **x**    |    **x**   |      **x**       |\n|maxItems        |            |            |       x      |            |                  |\n|create          |            |            |       x      |            |                  |\n|maxOptions      |            |            |       x      |            |                  |\n|selected        |            |            |       x      |      x     |        x         |\n|inline          |            |            |              |      x     |                  |\n\n\u003e Parameters with bolded **x** are mandatory. You can specify either *choices* \nor both *choiceValues* and *choiceNames* for `selectizeInput` and `radioButtons`.\n\n## Other features\n\nFor more information about these, check vignettes and documentation.\n\n- add instructions and additional item descriptions (also with *html* tags!)\n- randomize order of items\n- customize messages shown\n- pre-fill questionnaire with list of values\n- change labels depending on `reactive` expression value\n- customize automatically generated messages\n- add custom css rules for generated elements\n\n### Input to handle questions with Likert scoring scale\n\n`likertRadioButtons` is new input type created to accomodate the lack of\ninput that is meeting all requirements to create good looking and functional\ninput for questions with Likert-like scoring scale\n\n  - supports no initial selected value - which is essential to make sure that\n  the questionee selected the value themmselves. It is based on *radio* HTML input.\n  - displays semantic meaning of each value, or just *min* and *max*\n    - meaning of every value is displayed only if the user selects to make the\n    UI clean and presentable\n    - meaning of *min* and *max* values are displayed on left and right side of\n    the scoring scales\n  - sends the selected value to the server in its numeric form\n  - *UI presentation*:\n    - **with indicator** of the meaning of currently selected value (appears in place of\n    placeholder *Select value* - placeholder text also customizable!)\n    \n    ```{r eval=F}\n      likertRadioButtons(\n         inputId = \"with_ind\", label = \"With indicator\",\n         choiceValues = c(-2:2),\n         choiceNames = c(\"Very bad\", \"Slightly bad\", \"Not bad or good\",\n                         \"Slighty good\", \"Very good\")\n    ```\n    \u003cimg src=\"man/figures/likertRadioButtons_w_ind.png\" style=\"filter: drop-shadow(2px 2px 5px black); margin-bottom: 5px; max-width=518;\"\u003e\n    \n    - **without indicator** - only meaning of *min* and *max* is shown\n    ```{r eval=F}\n      likertRadioButtons(\n         inputId = \"wo_ind\", label = \"Without indicator\", \n         choiceValues = 1:7, choiceNames = c(\"Not much\", \"Many\"))\n    ```\n    \u003cimg src=\"man/figures/likertRadioButtons_wo_ind.png\" style=\"filter: drop-shadow(2px 2px 5px black); margin-bottom: 5px; max-width=522;\"\u003e\n\n\u003eCurrently the usability of `likertRadioButtons` is limited - there is no way\nto update the value or other elements after rendering. There is no function like `updateLikertRadioButtons` presently created. It is planned to be implemented\nsometime in the future. \n\u003eFor the time being, if you plan to use it outside of `Quetzio` and update\nits contents reactively, it is advised to do it using `renderUI`.\n\n## Thanks and credits\n\n- This package has been created within the 'discoRd' community. Feel free to join our \n[discoRd channel](https://discord.gg/FuTSvkSCVj){target=\"_blank\"}!\n- *shiny.quetzio* hexagon logo has been designed and created by very talented\nSandra Folwarczny. Big thanks for giving a life to *Questioning Quetzal*! \u0026#128513;\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FStatisMike%2Fshiny.quetzio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FStatisMike%2Fshiny.quetzio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FStatisMike%2Fshiny.quetzio/lists"}