There are a number of optional modifiers that can be included in
question blocks to control the appearance or behavior of the
audio modifier allows you to add audio to your questions. An
audio player will appear above the question, and the user can press
play to hear the sound.
The filename can be constructed with Mako. A plain file path will
be assumed to point to a file in the
static directory of the package
in which the YAML file resides. A package reference may also be
A URL beginning with
https may also be provided.
You can also play uploaded files:
Note that in this example, we use
file as the
datatype, which is
the standard way to upload files. You can also use the
microphone, which in some browsers (mostly on mobile platforms) will
launch an audio recording app to create the file to upload.
docassemble uses the HTML5 audio tag to allow users to play the
audio. Not all browsers support every type of audio file. In order
to make your audio files accessible to the greatest number of users,
then if you provide static audio files, you should include files in
For example, if your
audio specifier points to a file, such as
nyc_question.mp3, then your interview package should contain a file
nyc_question.mp3 in the
data/static directory. If you also
include an OGG version of this audio file, called
in the same directory, then docassemble will make both files
available to the user, and the user’s browser will use whichever file
works. In your
audio specifier, you can refer to either the
Or, if your
ogg alternatives are located in different
directories, you can do this:
Or, if you are using hyperlinks to files on another server, you can include different versions by doing something like this:
If you refer to an uploaded file, docassemble will take care of
ogg versions. When users upload an audio
file, docassemble tries to convert it to the appropriate formats.
For this to work, ffmpeg and pacpl must be installed on your system.
Currently, docassemble can handle audio files uploaded in
wav formats. If you need to be able to process
another type of audio file, docassemble’s source code can probably
be modified to support that audio type.
Note that there a number of limitations to playing audio in browsers. For example, older Android devices will not play audio retrieved through https, but will play the same audio retrieved through http.
See special variables for information about docassemble’s automatic text-to-speech features.
video specifier is just like the
except that it displays a video instead of an audio file.
docassemble uses the HTML5 video tag to allow users to play the
audio. Just as you should include both
ogg audio files,
you should include both
ogv video files, so that users of
many different browsers will all be able to see your videos. These
are the two formats that the HTML5 video tag most widely supports.
If you refer to an uploaded video file, docassemble will take care
of providing both
ogv versions. When users upload a
video file, docassemble tries to convert it to the appropriate
formats. For this to work, ffmpeg and pacpl must be installed on your
system. Currently, docassemble can handle videos uploaded in
mov formats. If you need to be able to process
another type of video, docassemble’s source code can probably be
modified to support that video type.
You can also use the
video specifier to embed YouTube and
Vimeo videos. For example, if you want to embed a YouTube video
and the URL for the video is
https://youtu.be/9bZkp7q19f0, you would write something like this:
If you want to embed a Vimeo video, the URL of which is
https://vimeo.com/96044910, you would write:
Note that you could not have written the above as this:
This would generate an error because YAML thinks square brackets
indicate a list of items, not plain text. If you want to write the
specifier on one line, write
video: "[VIMEO 96044910]".
[YOUTUBE ...] and
[VIMEO ...] assume that the aspect ratio of the
vide is 16:9. If the aspect ratio of the video is 4:3, you can use
[YOUTUBE4:3 ...] or
[VIMEO4:3 ...]. You can also explicitly state
that the aspect ratio is 16:9 by using
[YOUTUBE16:9 ...] or
In the web app, users can use the navigation bar to toggle between the
“Question” tab and the “Help” tab. The contents of the “Help” tab
consist of the contents of any
help specifiers in the question being
presented, followed by the contents of any
interview help blocks
contained within the interview.
You can add audio to your help text:
You can also add video to help text using the
interview help is available but question-specific
not available, the help tab is merely labeled “Help.” When
question-specific help is available, the help tab is bright yellow and
is marked with a star. If you want the label to be something other
than “Help”, you can add a
label inside the
question help button feature is enabled, and
help is available, a “Help” button will be
available on the button bar, which when pressed will show the help
tab. The button label is “Help” by default, but if a
provided to the question-specific
help, the button will bear this
label instead. When a help button is present, the help tab in the
navigation bar will always be labeled “Help,” and it will never be
highlighted in yellow.
The default label “Help” can be changed on a per-interview basis. If
you set an
interview help initial block and provide a
part of it, the value of this
label will be used instead of “Help”
as the name of the “Help” tab in the navigation bar.
By default, if a
decoration modifier refers to an image that has not
been defined in an
image sets or
images block, users will see an
error message. However, if you set the
use font awesome directive
in the Configuration to
True, then any reference to an image not
image sets or
images will be treated as the name of a
Font Awesome icon.
This method also works with inline icons.
script modifier contains raw HTML to be appended to the bottom
of the web page for the question.
css modifier contains raw HTML that will be appended to the HTML
It is best only to include CSS that is tied to specified HTML elements you include in your questions, rather than include CSS that has global effects (like the example above). Because of the way docassemble interviews work, CSS applied in one question will affect later questions until the screen is reloaded.
A docassemble interview can be configured to show a progress bar. This will show the user a progress indicator to give the user a sense of how much longer the interview will take.
The progress along the bar at any question needs to be set with the
progress modifier. For example:
The value of
progress needs to be a number between 0 and 100. If
the value is zero, the progress bar is hidden for the current
question. If the value is greater than 100, a full progress bar will
be shown. If the value is
null in YAML), then the
progress bar will be hidden and will not advance until it is set to
If the progress bar is enabled and the interview encounters a
question that does not have a
progress setting, the progress bar
will advance automatically. The amount by which the progress bar
automatically advances gets smaller as the progress
bar gets closer to 100%.
As a result, you do not need to attach a
progress setting to every
question; you can just set
progress on a few questions, and let the
automatic advancing mechanism take care of increasing the progress.
If the interview reaches a question with a
progress setting that is
less than the current position of the progress bar, the position of
the progress bar will stay the same. This ensures that the user
does not see the progress bar go backward.
A docassemble interview can be configured to show a left-hand
navigation bar on screens large enough to show one. The navigation
bar will contain a list of the sections in the interview, as specified
sections initial block or using the
function. In the navigation bar, the current section will be
section modifier to a question will update the current
section when the interview asks the question. This section will
continue to be the current section until another question is reached
that contains a
section modifier that specifies a different section.
As explained in the documentation for the
sections initial block,
you have the option of referring to a section by a keyword that is
different from the name of the section that is displayed to the user.
If you are using this feature, your
section modifier needs to refer
to the keyword, not the displayed name.
You can also set the current section using the
Normally, docassemble allows the user to click the back button to get back to earlier steps in the interview. Sometimes, it is necessary to prevent the user from doing so.
If you add a
prevent going back specifier to a
question, the web
app will not offer the user a back button while showing the question.
There is also a
prevent_going_back() function that accomplishes
the same thing from Python code. This may be more useful than the
prevent going back modifier if the need to prevent the user from
clicking the back button depends on the outcome of a process.
You can add a “Back” button to the buttons at the bottom of the screen
by setting the
back button modifier.
back button is set to
True or to Python code that evaluates
to a true value, then the button will be shown.
You can configure this on an interview-wide basis by setting the
question back button feature.
When you add a “Back” button to the buttons at the bottom of the
screen by setting the
back button modifier or the
button feature, you can change the text of the button using the
back button label modifier.
The text of the label can include Mako templating.
Using the modifiers
auto terms, you can specify the
definitions of particular vocabulary terms, and docassemble will
turn them into green hyperlinks. When the user clicks on the
hyperlink, a popup appears with the word’s definition.
You can define the vocabulary terms using
terms and then put curly
brackets around the instances of the words that you want to become
Alternatively, you can define the vocabulary terms using
in which case you do not need to use curly brackets, and the terms
will be highlighted in green every time they appear in the question.
If you want the terms to be highlighted every time they are used,
whether in curly brackets or not, use
If you want vocabulary terms to be highlighted throughout the
interview, not just for a specific question, you can use
auto terms as initial blocks.
docassemble’s language support allows a single interview to ask questions different ways depending on the user’s language. You can write questions in different languages that set the same variables. docassemble will use whatever question matches the active language.
The value of
language must be a two-character lowercase ISO-639-1
code. For example, Spanish is
es, French is
fr, and Arabic is
For more information about how to set the active language, see language support.
Some types of questions feature a “Continue” button. If you want the
label on the button to be something other than the word “Continue,”
continue button label modifier.
The types of questions that feature a “Continue” button include:
This modifier also allows you to customize the “Done” button that
generic object is a very powerful feature in docassemble that
allows interview developers to express questions in general terms.
The above example will cause docassemble to ask “Does Sally Smith
like cats?” if the interview logic calls for
neighbor is an object of type
Individual whose name has been set
to “Sally Smith.” The same question will also ask “Does William Jones
like cats?” if the interview logic calls for
teacher is an object of type
Individual whose name has been set
to “William Jones.”
x is a special variable that should only be used in
generic object questions. The above question definition tells
docassemble that if it ever needs the
likes_cats attribute for
any object of type
Individual, it can get an answer by asking this
If your interview needs a definition for
spouse is an object of type
Individual, docassemble will first
look for a question that offers to define
spouse.likes_cats. If no
such question exists, it will then look for a question that offers to
x.likes_cats, where the
generic object is
If no such question exists, it will look for
questions for the parent types of
Individual. The variables that
will be sought, in the order in which they will be sought, are:
This way, you can provide layers of
generic object blocks to handle
special cases as well as general cases, based on the object type. For
example, suppose your interview uses objects of type
Individual is a special type
Person, and an
Organization is also a special type of
Person. Suppose you have a general way of asking for a mailing
address (“What is so-and-so’s address?”), but you want to have a
special way of asking the question if you need the mailing address of
Organization (e.g., “What is ABC Incorporated’s primary place
of business?”). You would write a question with
Person for the general case, and a question with
Organization for the special case. The general question would be
used for objects of type
Person, and the
special question would be used for objects of type
You can also use
code blocks in a fallback
arrangement to capture special cases within object types. Suppose you
have a function
retrieve_ein() that can automatically determine an
organization’s Employer Identification Number (EIN), but only for
organizations organized as non-profits. For organizations not
organized as non-profits, you will need to ask the user for the EIN.
You could use the following two blocks to accomplish this:
.ein of an organization is needed, the
will be run, but the attribute will not be set if the organization is
not a non-profit. In that case, docassemble will notice that the
attribute is still not defined, and it will “fall back” to the
question that asks the user to manually enter the EIN.
As explained in the fallback section of the documentation, the order
in which these two blocks appear in the YAML file matters; the
code block will be tried first only if it appears later in the
YAML file than the
A similar feature to
generic object and its special variable
the special index variable
i. For more information about this
feature, see the index variable documentation and the documentation
in the groups section.
If your interview uses the roles
feature for multi-user interviews, the
role modifier in a
block will tell docassemble that if it ever tries to ask this
question, the user will need to have a particular role in order to
role can be a list.
In this case, the user’s role can either “advocate” or “supervisor” in order to be asked the question.
If the user does not have an appropriate role, docassemble will
look for a question in the interview in which
event has been set to
To cause the screen to reload in the web browser after a number of
seconds, use the
If you set
True, the screen on which the question is
asked will reload every 10 seconds. To use a different number of
reload to the number of seconds you wish to use. E.g.,
Since it is not good to reload the screen too quickly, you cannot use a number of seconds less than four. If the number of seconds is less than four, four seconds will be used as the number of seconds.
You can use Mako to determine the number of seconds. If the
reload value evaluates to
None, the screen will not
In some situations, you may need to tag a block in your interview with
a unique ID. You can use the
id specifier to do so.
In the absence of an
id specifier, docassemble would refer to a
block like this with a name like
Question_3 (if this block was the
third block in the interview). But with
id set to
docassemble will internally refer to this block with the ID
Also, in some situations, it can be important to tag your interview
blocks with a unique name that does not change when the blocks in the
interview YAML file change. This is because when docassemble
stores interview answers, it not only stores the current state of the
interview variables, but it also stores information about which
mandatory blocks have run to completion. When it does so, it tracks
the block using the ID for the block. If the IDs are arbitrary names
Question_3, users could encounter problems
For example, think about what would happen if a user started working
an interview on April 3, and got half-way through, and then saved her
answers and logged out, intending to log back in on April 10. Then
suppose that on April 8, you install a new version of the interview,
adding new functionality. When the user logs back in on April 10, her
interview answers might not be compatible with your new version of the
interview. For example, suppose that on April 3, the
code block known as
to completion. But when the user logs in on April 10 and resumes the
interview, the code block formerly known as
Question_12 is now known
Question_14. When docassemble evaluates her interview
session, it will determine that the
code block known as
Question_14 has not run yet, so
it will run that code block. This might cause information in the
user’s session to be overwritten. You can avoid problems like these
by tagging your code blocks with
id tags, so that the names of the
blocks do not change between versions of your interview.
Another way to avoid problems with the impact of software upgrades on
existing sessions is to use a different interview YAML file for each
version of an interview. So a user that starts
docassemble.tax:data/questions/tax-controversy-v2.yml will always
use the same YAML file, even when users who started later are using
id of a question needs to be set in order to use the
Usually, docassemble can figure out which variables a block is capable of defining. If a code block consists of:
then docassemble will try to run it if it needs a definition for
claim_is_valid. Sometimes, however, docassemble needs a hint.
You can explicitly indicate that a block sets a variable using
It also accepts multiple values:
As explained in how docassemble finds questions for variables,
if there is more than one
code block that offers
to define a particular variable, blocks that are later in the YAML
file will be tried first.
For example, suppose your friend developed a YAML file with
questions and code blocks that define the variables
docket_number. In your interview, you would
like to define
client.eligible the same way your
friend does. You can accomplish this by using
incorporate by reference your friend’s YAML file. But suppose you
don’t like the way your friend asks the question to determine
docket_number. No problem; just write a
question in your own
YAML file that defines
docket_number, and make sure that this
question appears after the
include block that incorporates
your friend’s YAML file. That way, your question will be used
instead of your friend’s.
However, there may be times when the relative placement of blocks within the YAML file is not a convenient way for you to designate which questions override other questions.
For example, suppose there are two
question blocks in your
interview that define
favorite_fruit. The second one is always used
because it appears later in the YAML; the second question supersedes
If you wanted the first question to be asked instead, you could rearrange the order of questions, but what if you wanted to keep the order the same?
One alternative is to use the
In this example, the
supersedes specifiers tell the
interview that the first question takes precedence over the second.
Another way of changing the order of precedence is to use the
order initial block.
If you have multiple
questions in your interview that define a
given variable, you can tell docassemble under what conditions a
given question may be asked. You do so by using the
Here’s how this works:
mandatoryquestion requires a definition of
answer, so the interview looks for blocks that offer to define
- The interview considers asking the “What is 2+2?” question. It considers this question first because it appears last in the YAML source.
- This question has a condition, so the interview evaluates the
Python expression. However, the expression depends on the
user_intelligence, which is undefined, so the interview asks a question to determine that value of this variable.
- When the user answers the
user_intelligencequestion, the interview tries to ask the
mandatoryquestion again, then looks for a definition of
answer, then considers asking the “What is 2+2?” question, then evaluates the
- If the expression evaluates to true, then the interview asks “What is 2+2?”
- If the expression evaluates to false, then the interview skips the
question and moves on to the “What is the square root of 50% of 32?”
question. It evaluates the
ifstatement, and will ask the question if the expression evaluates to true.
The content of the
if modifier must be a Python expression or a
list of Python expressions. If a list of expressions is provided,
each expression must evaluate to true in order for the question to be
By default, docassemble looks at every block in your interview and
automatically discerns what variables each block is capable of
setting. Then, when it is evaluating the interview logic, if it
encounters an undefined variable it goes through all the blocks that
are capable of defining the variable. As discussed above, if there
are multiple blocks that are capable of defining a variable, it tries
the ones that are later in the file first, unless an
block or a
supersedes modifier alters that order.
Sometimes, however, a block that docassemble tries to use to define a variable is one that you don’t docassemble to even consider when looking for a way to define a variable.
This is particularly likely to happen when you have code that changes the values of previously-defined variables.
For example, in this interview, the intention is that:
- A variable is gathered from the user
- The variable is reported back to the user
- Then variable is changed through code
- The variable is reported to the user again.
However, this interview does something the interview developer did not
intend: when it goes looking for a definition for
first thing it does is run the
mandatory code block that depends
time_of_day. So the first question that gets asked is
best_color. “Ugh!” the developer thinks, “that’s
not what I wanted! I only wanted that mandatory code block to be run
later in the interview.”
To fix this problem, the developer can modify the code block with
scan for variables: False:
Now, when docassemble goes searching for a block that will define
best_color, it will disregard the
code block that depends on
This modifier can be used on any block that sets variables to make it
effectively “invisible” to docassemble’s automatic logic. If a
block is marked with
scan for variables: False, the
sets modifiers will still be effective, so you can use them to
explicitly indicate that a block should be tried when the interview
needs a definition of a particular variable.
In this variation of the interview, for example, we first want to
best_color from the user. Then we want to determine
best_thing based on the time of day, and we want a side effect of
best_thing to be setting
best_color to something different.
If we did not use
scan for variables: False, then the interview
would never ask the user for
code block would
have been used to get an initial definition of
best_color. But by
turning off automatic variable scanning and explicitly indicating that
code block should only be used for determining the definition
best_thing, we were able to get the interview to behave the way
we wanted it to.
As discussed in the previous section, docassemble looks at every block in your interview and tries to discern what variables each block is capable of setting. However, sometimes it is not able to determine this correctly.
For example, if you have a
code block that uses a method to set an
attribute on an object, docassemble will not be able to see that
the code block is capable of setting the attribute. Here is one such
If you want docassemble to run this
code block when it needs a
user.allergies, then you need to add a
You can also give
sets a list of variables:
To make a note to yourself about a question, which will not be seen by
the end user, you can use a
comment specifier. It will be ignored
by docassemble, so it can contain any valid YAML.