Giter Site home page Giter Site logo

shinyforms's Introduction

shinyforms - Easily create questionnaire-type forms with Shiny

Donate

Note: The work on this package has paused, and it's currently looking for funding. Please contact me if your company would like to sponsor/fund this project. I receive a lot of emails about this package, but I cannot continue work on it without proper funding.

Click here to sponsor my work on shiny packages, and email me afterwards if you'd like me to continue working on shinyforms.

What does shinyforms do?

The idea of shinyforms is to let you create questions/polls/surveys as Shiny apps very easily. Kind of like mimicking a Google Form.

But, why?

Good question. You should read my blog post where I discuss how to mimick Google Forms with Shiny, and why I originally needed to do it. I've created a few Shiny apps that request user input and save it somewhere, and I wanted to make it super streamlined for anyone else to do so in the future. You can see an live example of a Shiny form here.

How do I use this?

First, install this package from GitHub

# install.packages("devtools")
devtools::install_github("daattali/shinyforms")

Then create your list of questions. Each question is a list with an id, type, title, and mandatory (mandatory is FALSE by default)

library(shiny)
library(shinyforms)

questions <- list(
  list(id = "name", type = "text", title = "Name", mandatory = TRUE),
  list(id = "age", type = "numeric", title = "Age"),
  list(id = "favourite_pkg", type = "text", title = "Favourite R package"),
  list(id = "terms", type = "checkbox", title = "I agree to the terms")
)

Then create your form information, which has an id, the list of questions, and the storage type (where responses get saved).

formInfo <- list(
  id = "basicinfo",
  questions = questions,
  storage = list(
    # Right now, only flat file storage is supported
    type = STORAGE_TYPES$FLATFILE,
    # The path where responses are stored
    path = "responses"
  )
)

That's all the information we need. Now we can add the form to a Shiny app by simply calling formUI() and formServer() from our Shiny apps' UI and server:

ui <- fluidPage(
  formUI(formInfo)
)

server <- function(input, output, session) {
  formServer(formInfo)
}

shinyApp(ui = ui, server = server)

Of course you could put more stuff in the app, but this is the beauty of it, the form is a "module" that you can just plug into any Shiny app anywhere you want. Every time you submit a response, it will be saved as a file in the responses directory. This example is the most basic usage.

Current features

  • Responses are saved to local files
  • Support for mandatory vs optional fields (all questions with mandatory = TRUE have to be filled out before the submit button can be clicked)
  • Can create a form with only one line in the UI and one line in the server
  • Can include multiple different forms in the same app
  • Clean and user-friendly way to catch and report errors
  • Questions and form data are in the format of R lists
  • Supported question types: text, numeric, checkbox
  • Ability to submit multiple responses for the same form (use multiple = FALSE in the form info list to disallow multiple submissions)
  • Admin mode support: if you add ?admin=1 to the URL, you will see buttons for viewing all submitted responses below each form. If you want to see all responses, you'll have to enter a password to verify you're an admin (since anybody can just modify the URL). The password is provided by the password in the form info list.
  • Support for more complex input validation that gives nice error messages when a field does not meet certain conditions (use the validations option in the form info)
  • Can have an optional "Reset" button that resets the fields in the form (use the reset = TRUE parameter in the form info)
  • Questions can have hint text, which is text just below the question title that gives a longer description (use the hint parameter of a question)

Future features

You can see all the features I want to support here (but it might take some time because I can't devote too much time to this package right now).

Another example

This example is similar to the previous one, but illustrates a few more features. It shows how to have two forms in one app, and how to use the admin viewing ability.

library(shiny)
library(shinyforms)

# Define the first form: basic information
basicInfoForm <- list(
  id = "basicinfo",
  questions = list(
    list(id = "name", type = "text", title = "Name", mandatory = TRUE,
         hint = "Your name exactly as it is shown on your passport"),
    list(id = "age", type = "numeric", title = "Age", mandatory = FALSE),
    list(id = "favourite_pkg", type = "text", title = "Favourite R package"),
    list(id = "terms", type = "checkbox", title = "I agree to the terms")
  ),
  storage = list(
    type = STORAGE_TYPES$FLATFILE,
    path = "responses"
  ),
  name = "Personal info",
  password = "shinyforms",
  reset = TRUE,
  validations = list(
    list(condition = "nchar(input$name) >= 3",
         message = "Name must be at least 3 characters"),
    list(condition = "input$terms == TRUE",
         message = "You must agree to the terms")
  )
)

# Define the second form: soccer
soccerFormInfo <- list(
  id = "soccerform",
  questions = list(
    list(id = "team", type = "text", title = "Favourite soccer team"),
    list(id = "player", type = "text", title = "Favourite player")
  ),
  storage = list(
    type = STORAGE_TYPES$FLATFILE,
    path = "soccer"
  ),
  multiple = FALSE
)

ui <- fluidPage(
  h1("shinyforms example"),
  tabsetPanel(
    tabPanel(
      "Basic info",
      formUI(basicInfoForm)
    ),
    tabPanel(
      "Soccer",
      formUI(soccerFormInfo)
    )
  )
)

server <- function(input, output, session) {
  formServer(basicInfoForm)
  formServer(soccerFormInfo)
}

shinyApp(ui = ui, server = server)

Notice how easy this is? After defining the forms with R lists, it's literally two function calls for each form to get it set up. A couple things to note: first, the soccer form uses the multiple = FALSE option, which means a user can only submit once (if you restart the Shiny app, the same user is able to submit the form again). Secondly, the first form uses the password option, which means that the admin table will be available IF you add ?admin=1 to the URL. To see the responses from the admin table, click on "Show responses" and type in the password "shinyforms". This app also uses several other features.

Using Google Sheets example

This example is similar to the first example, but illustrates how to use shinyforms with Google sheets as your storage type. In the example you can see that we need to first create a new Google sheet document and give it a header. From there on, we only need to pass the sheet's key to the storage list and shinyforms will do the rest.

library(shiny)
library(shinyforms)
library(googlesheets)

# Create a new google sheets file 
df <- data.frame(name = "", age = 0, favourite_pkg = "", terms = TRUE)
google_df <- gs_new("responses", input = df, trim = TRUE, verbose = FALSE)


questions <- list(
  list(id = "name", type = "text", title = "Name", mandatory = TRUE),
  list(id = "age", type = "numeric", title = "Age"),
  list(id = "favourite_pkg", type = "text", title = "Favourite R package"),
  list(id = "terms", type = "checkbox", title = "I agree to the terms")
)

formInfo <- list(
  id = "basicinfo",
  questions = questions,
  storage = list(
    # Right now, only flat file storage is supported
    type = STORAGE_TYPES$GOOGLE_SHEETS,
    # The path where responses are stored
    path = "responses",
    # Get the Google sheet key 
    key = google_df$sheet_key
    
  )
)

ui <- fluidPage(
  formUI(formInfo)
)

server <- function(input, output, session) {
  formServer(formInfo)
}

shinyApp(ui = ui, server = server)

Feedback

If you think you could have a use for shinyforms, please do let me know or file an issue. Don't be shy!

Notes

Please don't look at the code, it's hideous! This was done at runconf16 in just a few very short hours so it needs to be cleaned up quite a bit. Also, since so little time was spent building this package so far, it's very likely that the API will change. I'm completely open for input.

shinyforms's People

Contributors

baobabprince avatar daattali avatar magrathj avatar pkq avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

shinyforms's Issues

Select questions randomly from list or dataframe

I've been experimenting with shinyforms and it gets me really close to what I'm trying to build, which is a kind of crowdsourcing app dealing with genres in newspaper texts (i.e., I provide the text and ask is this 'news', 'information', 'ad', etc.) I have my texts and potential genres saved in a data frame, or, just as easily, a list, and I'd like to be able to show a text and questions, then after the user answers and opts to "submit another response" have a different question served. Currently I can pull random questions from the list when a new session is started, and I tried to invoke a new session with session$reload() and a value to generate a random number, but refreshing the page doesn't serve a new question. Is there an easy solution for this that I might be missing? Thanks!

googlesheets4

Can you rewrite your last example code with googlesheets4 instead of googlesheets?

Allowing a list of forms to be called by formUI

Hi @daattali

This is very nice and works well in this use case. I forked it in
https://github.com/fozy81/shinyforms
and tried to add the ability to add a list of forms in a single call of formUI. Not entirely successfully! I'm struggling with the new way to handle id using 'NS' function. So for instance, if you had a pre-made form e.g. name + address form, email form, and favourite package form. You could chain them together in a list and create a single form out of multiple sub-forms. This could make managing forms easier and prevent need to re-write or duplicate effort.

This is the same approach, I've used with my package (in draft stage!):
https://github.com/fozy81/rdatamill

Also i've saved the question/forms to a table as well as the answers in my package. Giving all the results/answers the same structure. For easier analysis later. Also easier to handle versioning of the forms. i.e. the questions/forms/validation rules may change over time - need a way to know what version of the form was used when the data was submitted. Anyway, my package is very badly coded and happy to support this shinyforms - if I can be useful and we can work out a way to handle the complexity of validation rules and version-ing of the forms.

This is maybe something to think about, I'll try helping with something more practical next - adding support for my input types.

Rendering questions based on the input

I try to render questions based on the initial input with a hand of renderUI function evoked within the server. However, I constantly fail. Do you have any guide on how should I do it?

Refresh button for responses in admin mode

I used shinyforms for a real case and people started filling it up.
It works well, I actually used the fork from @fozy81(adding the right dependency to the latest shiny) to get more input types.
In the admin mode, you can see the answers but you cannot refresh it. You need to refresh the page and log in again, which is a bit annoying.
Could we have a refresh button in the admin mode to load again the csv files?
Many thanks again Dean!

Can not install shinyforms from GitHub

Hi I have troubles with installing shinyforms. I tried devtools as well as remotes but there is the same error (see below). I have correctly installed also Rtools but it does not work... Can you please help me?

Many thanks!
Martin

> remotes::install_github("daattali/shinyforms")
Error: Failed to install 'unknown package' from GitHub: Timeout was reached: [api.github.com] Operation timed out after 10005 milliseconds with 0 out of 0 bytes received

Error in passwordInput()

Hi,

I am sorry if I made a stupid mistake, but I cannot reproduce any of the two examples provided in the README.md.
The error is

Error in passwordInput(ns("adminpw"), NULL, placeholder = "Password") : 
  unused argument (placeholder = "Password")

I tried to split the ui and server functions into two separate files but I obtained the same error.

Many thanks in advance

sessionInfo()
R version 3.2.4 Revised (2016-03-16 r70336)
Platform: x86_64-apple-darwin15.3.0 (64-bit)
Running under: OS X 10.11.4 (El Capitan)
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     
other attached packages:
[1] shinyforms_0.0.0.9000 shiny_0.13.2         
loaded via a namespace (and not attached):
 [1] R6_2.1.2          rsconnect_0.4.2.1 htmltools_0.3.5   tools_3.2.4       Rcpp_0.12.4       digest_0.6.9     
 [7] xtable_1.8-2      httpuv_1.3.3      miniUI_0.1.1      mime_0.4          shinyjs_0.5.2    

writing to STORAGE_TYPES$GOOGLE_SHEETS works with non empty googlesheet

writing to STORAGE_TYPES$GOOGLE_SHEETS works fine, but only with a google sheet already filled with a header-row and at least one more row. Otherwise I get an error

all(lengths == 1L | lengths == n) is not TRUE

from the function call of gs_add_row() as explained in its documentation.

so probably it would be a good thing to indicate the usage of googlesheets is also supported by your package with the current limitations of the googlesheets package.

Compatibility with googkesheets4

It seems that the package isn't compatible with the new API version of google sheets and the nre R package from tidyverse googlesheets4. Is it possible to fix it?

DT package is used but not mentioned in DESCRIPTION

I was just trying shinyforms and when running your example I got

> ui <- fluidPage(
+ formUI(formInfo)
+ )
Error in loadNamespace(name) : there is no package called โ€˜DTโ€™

No hurry though. I think people can figure it out for now ๐Ÿ˜‰

If they don't they will probably find this and see that the solution is install.packages('DT')

More input options

Dear Dean,

I am following your shinyforms for quite some time now. In the past I had to tinker in shiny to implement certain apps with surveying capabilities and it was horrible to have to repeat certain chunks while arriving at an app with zero reusability (you have to change the script to change the questions, types, etc.). This is why I think this package is well thought out. To partly reach its potential (google forms capabilities) it needs a wider range of input options.

Fortunately, shiny already has those: multiple choice radioButtons() and checkboxGroupInput(), dropdown selectInput(), date selectInput() and dateRangeInput(), and linear sliders sliderInput(). Do you think these will be available?

Thank you.

Error : invalid 'nchars' argument

Dear Dean,

I encounter some troubles while trying to run a shinform (even the examples you provided on your page).

Everytime I try to run an app, the following error message appears in the Internet browser window and on the R console :
Error : invalid 'nchars' argument

Could you please help me finding what the cause is?

Thanks.

json schema and json-edit

Great to see progress on this. I think it will be a very valuable. I'll attempt to write out some of the thoughts that I had in my head for #1. I wondered if we could leverage JSON schema for validation/meta and then build/use something like json-editor or alpaca to quickly create a usable form. I did some tests a while ago auto-building a JSON schema from a R list, so you could have a

sample input list -> create a JSON schema -> could be supplemented or customized by advanced users -> create a form that could be used with or without Shiny

I might be way off, but since you seemed very open to input, I thought I would share my very preliminary thoughts.

I had a list of some applicable JavaScript in timelyportfolio/buildingwidgets#35.

have some thoughts here

I will be following along closely. I have some thoughts here. Do you have an idea for infrastructure or JavaScript libraries, templates, schema? Look forward to this project.

Allow generating a full Shiny app (ie. an actual "app.R" file) that just hosts a form

The main use of the package is to provide Shiny modules (but users don't need to know that, it abstracts that complexity away from them) so that a form can be plugged into any Shiny app. But it could be nice for people who want to make the form an entire standalone app to let them do that (a couple women from runconf16 told me they'd love that)

Results table additions

  • Should results be allowed to be shown to everyone? Maybe only after submission sometimes? Currently you need to add ?admin=1 in the URL and only if there's a password supplied in the form info, you can see it
  • Where should the results table go? Currently it's just under the form
  • Show some basic stats/analytics.....? This could only be supported if the results are shown somewhere separate, not as just a table under the form

Just some stuff to think about

Time Stamp column in diffrenet format ?

Hi,

Currently the time stamp in "Admin Panel" is displaying in below format. Is there any function available in shinyForms to get in order as MM-DD-YYYY HH:MM:SS ?

image

Shinyforms compared to concerto platform

First of all: I think this package is a great idea!

I was wondering, ar you aware of the existence of Concerto platform? R-based and also a wat to publish forms on the net. Do you think that shinyforms could, in potention, evolve into something similar? To my opinion Concerto acted rather slow (and I must admit, that was two versions ago), so any approvement on things like speed would be very welcome. Also I think that in the end a well performing, secure connected, safe, open source testrunner application with R as its score calculator could cause a revolution in the world of assessments. It would be very easy to start as a new and competing test publisher.

Just some thoughts.

Kind regards

I can't install the package

When i install with
install.packages("shinyforms")
it said not available for R version 3.6.3

then i install with devtools::install_github("daattali/shinyforms")
it said

WARNING: Rtools is required to build R packages, but is not currently installed.

Hide question based on conditional logic

In case of large questionnaires, some questions may only be relevant if an answer to a previous question wa positive:

  1. Do you own a car? YES / NO <- radiobuttons question.
  2. What Type of Car is this <- radibuttons : Truck, Sedan , Bus.

Asking the question 2 is meaningless if the answer to question 1. was "NO".

To prevent asking unnecessary questions it would be crucial to implement some kind of conditional logic into these questions, so that only the relevant ones show up.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.