Edit this page on GitHub

Question blocks

In the docassemble web app, every screen that a user sees is generated by a question block, which is a section of YAML code that contains a question specifier.

All blocks in an interview file must either be initial blocks, code blocks, or contain a question specifier.

The question block

question: |
  What is the airspeed velocity of an unladen swallow?
fields:
  - Velocity: swallow_velocity
question

By including the above YAML block in your interview file, you are telling docassemble that if it ever needs to know the value of swallow_velocity, it should ask the user the question “What is the airspeed velocity of an unladen swallow?” and provide the user with an input box labeled “Velocity” in which the user can type the answer.

Like many things in docassemble, the question specifier can contain Markdown and Mako. For example:

question: |
  What is the *airspeed* velocity of an unladen ${ african_or_european }
  swallow?
fields:
  - Velocity: swallow_velocity
question-markup

In this example, the word “airspeed” is italicized, using the Markdown syntax for italics. The type of swallow is given by a variable (african_or_european), the value of which ("African") is incorporated using Mako. (One of the features of Mako is that anything enclosed in ${ ... } is evaluated as Python code.)

The subquestion specifier

The optional subquestion adds text underneath the question. It is typically used to explain the question in more detail, if such an explanation is necessary.

question: |
  What is the airspeed velocity of an unladen swallow?
subquestion: Be careful how you answer.
fields:
  - Velocity: swallow_velocity
subquestion

The under specifier

The optional under specifier adds text underneath the buttons.

question: |
  What is the airspeed velocity of an
  unladen swallow?
fields:
  - Velocity: swallow_velocity
under: |
  Note: if you did not catch this
  movie reference, you need to
  improve your cultural literacy.
under

The right specifier

The optional right specifier adds text on the right-hand side of the screen, or below the question on small screens.

question: |
  What is the airspeed velocity of an
  unladen swallow?
fields:
  - Velocity: swallow_velocity
right: |
  ### Note
    
  If you did not catch this
  movie reference, you need to
  improve your cultural literacy.
right-centered

If your interview has questions that use the right specifier, you might want to set the centered feature to False so that the text on the right is wider.

features:
  centered: False
---
question: |
  What is the airspeed velocity of an
  unladen swallow?
fields:
  - Velocity: swallow_velocity
right: |
  ### Note
    
  If you did not catch this
  movie reference, you need to
  improve your cultural literacy.
right

Using questions to set variables

Here is a brief summary of the types of questions that can be asked. More detail about how these question types work is provided in the next section.

True or false: yesno and noyes

A yesno question will set a variable to True or False when a Yes or No button is pressed. noyes does the opposite.

question: |
  Are you at least 18 years of age?
yesno: over_eighteen
yesno

Multiple choice: choices or buttons

You can ask a multiple-choice question by providing a list of choices:

question: |
  What type of shoes do you wear?
field: target_variable
choices:
  - Sneakers
  - Sandals
  - Clogs
  - Other
choices

Or, if you would prefer to use one-click buttons instead of “radio buttons” in combination with a “Continue” button, use can use buttons instead of choices.

question: |
  What type of belly button do you
  have?
field: target_variable
buttons:
  - Innie
  - Outie
  - No belly button
buttons

The variable indicated by field will be set to the value supplied in the choices/buttons list.

Acknowledgement button: field

If you simply want the user to acknowledge something by clicking “Continue,” provide a field without buttons or choices.

The variable indicated by field will be set to True when the user clicks “Continue.”

field: target_variable
question: |
  Welcome to the interview.
subquestion: |
  When you are ready to begin, press
  Continue.
continue

One or more fill-in fields: fields

You can ask the user to fill in multiple fields using fields.

question: |
  What are your favorite things to eat?
subquestion: |
  Please be specific.
fields:
  - Vegetable: target_variable
  - Fruit: other_target_variable
text-field

There are many other types of input that you can gather with fields, including large text areas, file uploads, radio buttons, and checkboxes.

There are a variety of ways you can insert text into the list of fields to help guide the user. If you know HTML, you can insert arbitrary HTML, CSS, and Javascript.

User’s signature: signature

You can ask the user to write his or her signature using signature:

question: |
  Sign your name
subquestion: |
  By signing your name, you agree to
  our terms and conditions.
signature: target_variable
under: |
  ${ user }
signature

The signature will be stored as an image file in the variable indicated by signature.

Ending screens

Sometimes, the purpose of your question is not to gather information but to present an end screen to the user. You can create such “questions” by marking them as mandatory:

question: |
  Congratulations!
subquestion: |
  You are all done with the interview.
mandatory: True
terminal-screen

If you have more than one possible ending screen in your interview, use the event feature described below.

Special buttons

Using the buttons or choices syntax described above, you can add special buttons to a screen. These buttons are special because they do not set a variable.

These buttons are particularly useful on “terminal” screens.

question: We are all done.
buttons:
  - Exit: exit
  - Restart: restart
mandatory: True
exit-buttons

The above example allows the user to “exit” the interview (i.e., to be redirected to a different web site) or “restart” the interview (i.e., go back to the beginning, with all of the answers forgotten).

There are six special button functions:

  • restart
  • new_session
  • exit
  • logout
  • exit_logout
  • leave
  • continue
  • refresh
  • signin

restart resets the user’s variable store, except that any parameters that were originally passed through as URL parameters will be used again. The user is redirected to the first question of the interview.

new_session does not disturb the current interview session, but starts a new session for the same interview. The original URL parameters are not used.

exit means that the user’s variable store will be erased and the user will be redirected either to the URL given by the associated url text, or if no url is defined, to the exit page defined in the configuration. If the user tries to come back to the interview again, he will start the interview again, as though it had never been started. Original URL parameters will be lost.

For example:

question: |
  Congratulations, you found Nemo!
buttons:
  - Try again: restart
  - Learn More: logout
    url: https://en.wikipedia.org/wiki/Amphiprioninae
mandatory: True
exit-url

Mako can be used in the url text.

logout logs the user out, if the user is logged in.

exit_logout does the same thing as exit, except that it also logs the user out, if the user is logged in.

leave works like exit except that the user’s variable store will be left intact. This means that if the user comes back to the interview again, he will pick up where he left off.

continue means that docassemble will move on from the question without really doing anything. Here is an example of when it is useful:

mandatory: True
code: |
  menu_items = [ action_menu_item('Visit Cow', 'see_cow') ]
---
event: see_cow
question: |
  Moo!
subquestion: |
  [FILE cow.jpg]
  
  Cow illustration designed by
  [Freepik](http://www.freepik.com/free-photos-vectors/animal)
buttons:
  - Continue: continue
---
question: Welcome to the interview
subquestion: |
  Check out the menu in the
  upper-right corner.
mandatory: True
menu-item

This example uses the actions feature to present a special screen that shows a picture. This screen does not set any variable, but the user can click the button to “continue” with the normal course of the interview.

refresh re-runs the interview logic. It has much the same effect as refreshing the page in the browser. It is useful in multi-user interviews when the user is waiting for another user to finish entering information. It can also be useful in interviews that use external data sources.

mandatory: True
code: |
  tell_time
---
event: tell_time
question: |
  The current time is
  ${ current_datetime().format_time() }.
buttons:
  - Tell me again: refresh
refresh

signin redirects the user to the docassemble sign-in page.

mandatory: True
code: |
  if user_logged_in():
    goodbye_page
  else:
    sign_in_page
---
question: |
  Please sign in
buttons:
  - Sign in: signin
sets: sign_in_page
signin

Instead of using buttons, you can use choices to get a radio list instead of a selection of buttons.

question: We are all done.
choices:
  - Exit: exit
  - Restart: restart
mandatory: True
exit-choices

The functionality is the same.

The command() function allows you to do similar things with Python code. In addition, the url_of() function provides URLs that accomplish a similar purposes.

Mixing special buttons with buttons that set a variable

Note that since “special” buttons do not set a variable, you should not include a field in the question. If you include a field in the question, docassemble will assume you are creating an ordinary multiple choice question.

If you wish to mix “special” buttons with buttons that set a variable, you can use the command() function in code to trigger the same effects as clicking on a “special” button.

The following example uses a mandatory code block to determine the course of the interview. Depending on the answer to an ordinary multiple choice question, it either exits from the interview or proceeds to another screen.

mandatory: True
code: |
  if user_choice == 'exit':
    command('exit')
  elif user_choice == 'proceed':
    final_screen
---
question: |
  Warning!
subquestion: |
  Proceeding with this interview may
  result in despair-inducing levels
  of liability.
field: user_choice
buttons:
  - Exit: exit
  - Keep going: proceed
---
event: final_screen
question: |
  Hey, I warned you.
exit-buttons-mixed-code

Another alternative is to use multiple-choice buttons that run code:

question: |
  Warning!
subquestion: |
  Proceeding with this interview may
  result in despair-inducing levels
  of liability.
buttons:
  - I understand:
      code: |
        attitude = 'careful'
  - I do not care:
      code: |
        attitude = 'reckless'
  - Get me out of here: exit
---
mandatory: true
question: |
  % if attitude == 'reckless':
  You are foolish!
  % else:
  Ok, we are proceeding with caution.
  % endif
exit-buttons-mixed

Special screens: event

Some screens are shown to the user when a special event occurs.

For example, if you have a multi-user interview and the interview reaches a point where the user cannot proceed until the other interviewee answers a question, the interview will present the user with a question that explains why he or she needs to wait.

Or, you might want to provide the user with the ability to review his or her answers on a single screen, using the review functionality.

The event specifier advertises to the interview logic that the question should be asked if a special event occurs.

question: |
  This is a special screen.
event: show_special_screen
event-example

This specifier can be used to indicate an ending screen, where your interview has more than one possible ending screen and you use interview logic to direct the user to the appropriate screen.

question: |
  Which door do you choose?
field: door_choice
choices:
  - Door Number 1
  - Door Number 2
---
mandatory: True
code: |
  if door_choice == 'Door Number 1':
    good_luck
  if door_choice == 'Door Number 2':
    bad_luck
---
question: |
  You walk into a field of clover.
event: good_luck
---
question: |
  You walk into a stinky swamp.
event: bad_luck
doors

In this example, good_luck and bad_luck are actually names of Python variables. However, they are Python variables that will never be defined. If a reference to these variables is made, as it is in the mandatory code block, docassemble will locate the good_luck and bad_luck questions, just as it looks for questions that offer to define any variable.

See interview logic for more information about how to give direction to your interview by adding code blocks that are marked with the mandatory modifier.

The event specifier is also used to create screens that the user can reach from the menu or from hyperlinks embedded in question text. For more information, see event, url_action(), process_action(), action_menu_item(), and menu_items.