To instruct docassemble to store user input that it receives in
response to a question, you need to include in your
variable name to hold the information. You also
need to indicate what type of variable it is (e.g., text, a date, a
number), and how you want to ask for the input (e.g., with a label).
This section explains the many ways that variables can be populated
Variable names are Python identifiers, which means they can be any
sequence of uppercase or lowercase letters, digits, and underscores,
except the first character cannot be a digit. No spaces are allowed
and no punctuation is allowed except for the underscore,
The following are valid variable names:
nyancat(variables are case-sensitive, so this is not the same as the above)
__f645456DG_greij_43(but why would you use something so ugly?)
USER_PHONE_NUMBER(ok, but why are you yelling?)
The following are not valid variable names, and if you try to use such variable names you will may get an error or unexpected results:
8th_plaintiff(you can’t begin a variable name with a number; Python will say “invalid syntax”)
Nyan-Cat(this is arithmetic:
fried.fish1(this is valid code, but Python will think you are referring to the attribute
fish1of the object
user's_phone_number(apostrophes are not allowed; Python recognizes them as single quotes)
favorite animal(spaces are not allowed)
beneficiary#1(punctuation marks other than
_are not allowed)
applicant_résumé(only plain alphabet characters can be used)
If you find yourself using variable names like
automobile_two, you should learn about groups and
generalizing. It would make more sense to work with
If you find yourself using variable names like
retirement_income, you should learn
DADict (a type of group). It would make more sense to
work with variables like
income['retirement']. Then you
could generalize the questions you ask.
And if you find yourself using variable names like
should learn about objects. It would make more sense to work with
defendant.spouse.birthdate. There are many advantages of working
with objects, such as being able to write
defendant.spouse.age_in_years() to calculate the ages of people
based on their birthdates.
yesno causes a question to set a boolean (true/false)
variable when answered.
In the example above, the web app will present “Yes” and “No” buttons
and will set
True if “Yes” is pressed, and
False if “No” is pressed.
noyes is just like
yesno, except that “Yes” means
False and “No” means
Note that yes/no fields can also be gathered on a screen along with
other fields; to make screens like that, use
These are just like
noyes, except that they offer a
third choice, “I don’t know.” If the user selects “I don’t know,” the
variable is set to
None, which is a special Python constant that
represents the absence of a value.
question block with
buttons will set the variable
field to a particular value depending on which of the
buttons the user presses.
buttons must always refer to a list, so that docassemble knows
the order of the buttons.
If an item under
buttons is a YAML key-value pair (written in the
- key: value), then the key will be the button label that the
user sees, and the value will be what the variable identified in
will be set to if the user presses that button.
An item under
buttons can also be plain text; in that case
docassemble uses this text for both the label and the variable
In other words, this:
is equivalent to this:
A powerful feature of
buttons (which also works with
combobox) is the ability to use Python
code to generate button choices. If an item under
buttons is a
key-value pair in which the key is the word
docassemble executes the value as Python code, which is expected
to return a list. This code is executed at the time the question is
asked, and the code can include variables from the interview.
docassemble will process the resulting list and create additional
buttons for each item.
Note that the Python code needs to return a list of key-value pairs (Python dictionaries) where the key is what the variable should be set to and the value is the button label. This is different from the YAML syntax.
This is equivalent to:
You can mix choices that are specified manually with choices that are specified with code:
You can use
buttons as an alternative to
yesno where you want
different text in the labels.
In order for the variable to be set to the special Python values
False, you need to make sure that the only values you
False, and nothing else, just like in the
example above. If you include a different value, your variable will
be set to
'False', which could cause problems.
To provide a multiple choice question with “radio buttons” and a
“Continue” button, use
field with a
You can specify a default value using
Another way to set a default is by adding
default: True to the
choice that you want to be the default.
You can also provide help text for a radio button using
These customizations can also be specified when building a list of choices using code:
To provide a multiple choice question with a dropdown selector, use
field with a
To provide a multiple choice question with a “combobox” selector, use
field with a
The “combobox” selector allows users to choose a selection from a list or enter a value of their own.
To add a decorative icon to a
buttons choice, use a key/value pair
image as an additional key.
This works with
choices as well:
It is not possible to decorate
combobox choices with
If you create the list of choices with
code, you can specify an image by
including an additional key/value pair within an item, where the key
There is an additional feature available when you assemble buttons
code: you can use
DAFileList objects to indicate the image. This example uses an
uploaded image file as the source of the image for one of the buttons:
Multiple choice questions can embed
question blocks and
blocks. These questions are just like ordinary questions, except they
can only be asked by way of the questions in which they are embedded.
You embed a question by providing a YAML key-value list (a
dictionary) (as opposed to text) as the value of a label in a
question blocks can be useful sometimes, it is
generally not a good idea to structure interviews with a lot of
embedded questions. You will have more flexibility if your questions
stand on their own. Embedded blocks cannot use the
modifier or index variables.
It is also possible for multiple-choice questions to embed
blocks that execute Python code. (If you do not know what
blocks are yet, read the section on code blocks first.) This can be
useful when you want to set the values of multiple variables with one
The question above tells docassemble that if the interview logic
calls for either
car_make, the question should be
tried. When the user clicks on one of the buttons, the code will be
executed and the variables will be set.
question with a
field and no
buttons will offer the user a
“Continue” button. When the user presses “Continue,” the variable
field will be set to
So far, we have discussed questions that set a single multiple-choice
variable and the use of
field by itself to set a
single variable to
True. These are helpful when you are collecting
False values or multiple choice values. However,
docassemble’s primary tool for collecting information in is the
fields allows you to collect many different
types of information and to collect more than one piece
of information on a screen.
fields specifier must refer to a YAML list of one or more
“fields”. Each list item must consist of one or more key/value pairs.
One of these keys (typically) is the label the user sees,
where the value associated with the key is the name of the variable
that will store the user-provided information for that field. The
other key/value pairs in the item (if any) allow you to modify how the
field is displayed to the user.
These field modifiers are distinguished from label/variable pairs based on the key; if the key uses one of the names listed below, it will be treated as a field modifier; if it is anything else, it will be treated as a label.
The next section describes the different types of variables you can
fields and the different types of user interfaces you
The possible values of
In most cases,
datatype controls both the user interface and the
format in which the data is stored. But for certain multiple choice
questions, you can use
datatype to indicate how you want the data
stored, and use
input type to indicate the type of user interface
to use. The possible values of
input type are:
You can change the number of rows in the text area using the
The default number of rows is four.
datatype: date provides a date entry input box. The style of the
input box depends on the browser.
Validation is applied to ensure that the date can be parsed by
The variable resulting from
datatype: date is a special Python
object of the class
DADateTime, which is a subclass of the
standard Python class
datetime.datetime. So if the name of the
date variable is
date_of_filing, then you can do things like:
Note that the field on the screen only asks for a date, but
DADateTime represents both a date and a time. The time portion of
DADateTime object will be set to midnight of the date. If you
DADateTime with a time other than midnight, you can use the
.replace() methods of
generate a new object with the same date but a different time.
For more information about working with date variables, see
the documentation for the date functions. These functions are
generally very flexible about formats, so you can pass a string like
'12/25/2018' or a date object, and the function will produce the
correct result either way.
If you set a
default value for a date field, write the date in the
format YYYY-MM-DD. Many browsers have built-in “date pickers” that
expect dates to be in this format. See Mozilla’s documentation of
the date input field. If the browser uses a date picker, then your
interview will see text values in the form YYYY-MM-DD, but on other
browsers, like Firefox, the format may be some other format.
datatype: time provides an input box for times. The style of the
input box depends on the browser.
Validation is applied to ensure that the time can be parsed by
The resulting variable will be an object of type
datatype: datetime provides an input box for dates and times
together in one field. The style of the input box depends on the
browser. Note: not all browsers have a “widget” for combined date and
times, and users might be confused if they are presented with a plain
text box. For this reason, use of
datatype: datetime is not
recommended until browser support for the
becomes more widespread.
Validation is applied to ensure that the time can be parsed by
datatype: email provides an e-mail address input box.
You can use the optional field modifier
step to limit the number to a
certain number of decimal places and to control the way the browser
widget controls work:
The variable will be set to a number, just as if
was used. For information about how to display currency values, see
If the currency symbol defined by the locale is not the currency you
want to use, you can include an
initial block that calls
set_locale() with the
currency_symbol keyword parameter set to
the symbol you want to use. This will set a default value for
datatype: currency fields and for the
Keep in mind that the variable stored by a
datatype: currency field
is just a number, so it is not aware of the currency denomination that
was presented to the user when the information was collected.
You can also override the currency symbol on a field-by-field basis by
currency symbol field modifier.
As this interview demonstrates, the
currency() function accepts an
optional keyword parameter
symbol that allows you to override the
symbol that is displayed.
datatype: range shows a slider that the user can use to select a
number within a given range. The range must be supplied by providing
max values. An option
step value can also be provided,
the default of which is 1.
You can also include an optional
scale, which you can set to
files datatypes within a
fields list, you can
allow users to upload one or more files.
datatype: file indicates that the user can upload a single file.
The variable is set to a
DAFileList object containing the
necessary information about the uploaded file.
datatype: files indicates that the user can upload one or more
files. The variable is set to a
DAFileList object containing the
necessary information about the uploaded files.
If your users upload digital photos
into your interviews, the uploads may take a long time. You can
configure an upload field so that images are reduced in size before
they are uploaded by modifying your field definition with a
maximum image size. The image will be reduced in size so that is
no taller than or wider than the number of pixels designated by
maximum image size.
In this example, images will be reduced in size to no more than 100 pixels in height or width:
Note that the image file type of the uploaded file may be changed to PNG during the conversion process. Different browsers behave differently.
If you have a lot of document upload fields, you can set a default
maximum image size on an interview-wide basis with the
maximum image size interview feature and on a site-wide basis with
maximum image size configuration directive. If you have a
default set up, but you want to override it for a particular field,
you can set the
maximum image size field modifier to
By default, any file that a user uploads
during a session will be deleted when that session is deleted. If you
want the file to continue to exist after the session is deleted, you
can set the field modifier
True. The modifier also
accepts Python code; if the code evaluates to a true value, the file
will persist. This has the same effect as calling the
.set_attributes() method on the file variable using the keyword
By default, any file that a user uploads will
only be downloadable by the user or by an administrator. If you want
the file to be accessible to anyone, set the field modifier
False. The modifier also accepts Python code; if the code
evaluates to a false value, the file will be available to anyone.
This has the same effect as calling the
on the file variable using the keyword attribute
If you set
private: False, then the file
is available to anyone, including non-logged in users. Even a bot
that guesses URLs could download the file. If you want to share with
particular users, you can indicate specific users using the
users modifier. If
allow users refers to a YAML list, the list
is expected to be a list of e-mail addresses of users or integers
indicating the numeric user IDs of users. If
allow users refers
to text, the text is treated as a single item. If
refers to a YAML dictionary, the single key of which is
can define the list with Python code. The code is expected to
evalute to an e-mail address, an integer user ID, an
DAList of any of the
above. You can also use the
.user_access() method to control
which users have access to a file.
Instead of granting access to specific
other users, you can grant access to categories of users by
referencing privileges by name, such as
advocate. If the
allow privileges modifier refers to a YAML
list, the list items are expected to be text items like
allow privileges refers to a string, it is treated
as a single item. If it refers to a YAML dictionary, the single key
of which is
code, you can define the privileges using Python code,
which is expected to evaluate to text (e.g.,
'user') or a list of
text strings (e.g.,
['user', 'developer']). You can also use the
.privilege_access() method to control which users have access to a
There are a few other data types that result in file uploads:
datatype: camera is just like
with an HTML5 input type that suggests using the device’s camera to take a
picture. On many devices, this is no different from
datatype: user is just like
camera, except with
an HTML5 input type that suggests using the device’s front
datatype: environment is just like
camera, except with an HTML5 input type that suggests using the
device’s rear (environment-facing) camera.
Whether these special data types do anything different from the
data type is dependent on the web browser. Mobile browsers are the
most likely to respond to these features.
For more information about uploading files, and for instructions on uploading signature images, see the Uploads subsection.
datatype: yesno will show a checkbox with a label, aligned with
datatype: noyes is like
datatype: yesno, except
with True and False inverted.
Sometimes, when you are using a series of
these checkboxes, you might want to have a “none of the above”
selection. To do this, add a field for the selection, and associate
it with a variable. (Your interview does not need to use the
variable.) Then modify the field with
uncheck others: True.
This will cause the field to act as a “none of the above” field for
all the other yes/no checkbox fields on the page. If you want the
field to only relate to specific other fields, use a list of the
variable names of those fields instead of
datatype: checkboxes will show the
choices list as
checkboxes. The variable will be a
DADict (a type of dictionary
specific to docassemble) with items set to
depending on whether the option was checked.
As you can see in this example, the keys of the resulting dictionary
are the names of fruit, the values that are checked are
the values that were not checked are
In the example above, the keys of the dictionary are the same as the labels displayed to the user. If you want labels to be different from the keys, you can specify the choices in the following manner:
You can generate checkbox choices with code:
To set default values in a checkbox list, you have a few options.
If you want to select just one option, just indicate the name of the option:
If you want to select multiple options, indicate a YAML list:
You can also indicate your defaults in the form of a YAML dictionary:
You can also use Python code to generate the defaults:
You can also include
input type: dropdown:
The “combobox” selector allows users to choose a selection from a list or enter a value of their own.
input type: ajax looks like a
combobox, but retrieves its
choices from the server using Ajax, based on what the user types.
It is useful when the number of possible values is too large to send
to the browser all at once.
input type: ajax, you also need to supply an
url_action_call() to call the given action. In return, it expects
a JSON list of items.
code block that carries out the
action should always begin
set_save_status('ignore'). If you leave this out, then a step
will be added to the interview each time the results are fetched. The
code block should always end with a call
The data that you pass to
json_response() can be in one of three
- A list of pieces of text;
- A dictionary in which the keys are the underlying values (what the variable will be set to) and the values are labels (what the user sees and types); or
- A list of lists, where the first item in each sub-list is the underlying value and the second item is the label.
In order to avoid sending too many requests to the system, the requests are throttled so that they happen no more than once every two seconds.
The list will not start showing results until the user types at least
four characters. If you want to use a different number of characters
as the minimum, set
trigger at. For example:
datatype: object is used when you would like to use a variable to
refer to an existing object. You need to include
choices, which can be a list of objects.
datatype: object in combination with
you can create questions that either set the attributes of an object
or set the object equal to another object.
In this example, if the gardener and the cook are the same person, the interview effectively does the following in Python:
Please note that
datatype: object cannot be used with
generic object modifier if the variable being set is
For a fuller discussion on using multiple-choice object selectors, see the section on selecting objects, below.
datatype: object_checkboxes is used
when you would like to use a question to set the elements of an object
DAList (or a subtype thereof). The choices in
choices (optionally modified by
exclude) will be
presented to the user as checkboxes. The
.gathered attribute of the
variable will be set to
True after the elements are set. See
groups for more information.
You can also use
datatype: object_checkboxes on variables that
already exist in your interview. You would need to do this if you
wanted the variable to be a subtype of
DAList. If you use a
variable name that already exists, note that the
question will only
be used when the
.gathered attribute is needed. To avoid questions
False. For example:
Another advantage of using an already-existing variable is that the
choices in the question will default to the current elements in the
list. In this example, we use the
.append() method to initialize
the list of villains.
From the user’s perspective,
datatype: ml works just like
text (which is the default if no
datatype is indicated), and
datatype: mlarea works just like
From the interview developer’s perspective, however, the variable that is set is not a piece of text, but an object representing a classification of the user’s input, based on a machine learning model that is “trained” to classify user input.
For more information about how to use machine learning variables, see the machine learning section.
You can use custom data types by declaring a subclass of
CustomDataType in a Python module with class attributes that
describe the data type. For example:
This will allow you to write:
The available class attributes are:
name(required) - the
datatypename. The only valid characters are alphanumeric characters, the hyphen, and the underscore.
container_class- a CSS class for the parent container. By default, this will be set to
da-field-container-datatype-followed by the
input_class- a CSS class for the
<input>element. By default, this will be set to
dafollowed by the
<input>element. By default, this will be set to
The following are the keys that have special meaning within a list
datatype affects how the data will be collected, validated and
stored. For a full explanation of how this is used, see
input type is similar to
datatype. It is used in situations
datatype might be
number, etc., but you want
the field to use a particular type of multiple-choice input element,
such as a list of radio buttons or a combobox.
For a full explanation of how this is used, see above.
required affects whether the field will be optional or required. If
a field is required, it will be marked with a red asterisk, and input
validation will be enforced to make sure the user provides a value.
If the user skips a non-required field, the variable will be blank for
text-based fields and
None for multiple-choice and yes/no fields.
The value of
required can be
False. By default, all
fields are required, so you never need to write
unless you want to.
Instead of writing
False, you can write Python code.
This code will be evaluated for whether it turns out to be true or
false. For example, instead of
False, you could use the
name of a variable that is defined by a
yesno question (as long as
that variable was defined before the screen loads; the red asterisk
cannot be toggled in real time within the browser).
You can guide users as to how they should fill out a text field by
showing greyed-out text in a text box that disappears when the user
starts typing in the information. In HTML, this text is known as the
placeholder. You can set this text for a text field by setting
hint. You can use Mako templates within
You can provide contextual help to the user regarding the meaning of a
field using the
help field modifier. The label will be green to
indicate that it can be clicked on, and the value of
appear on the screen when the user clicks the green text. You can use
Mako templates within
You can provide a default value to a field using
default. You can
use Mako templates in
choices field modifier is used with multiple-choice fields. It
must refer to a list of possible options. Can be a list of key/value
pairs (key is what the variable will be set to; value is the label
seen by the user) or a list of plain text items (in which case the
label and the variable value are the same).
choices indicates a list of objects from
which the user will choose. For more information about using objects
in multiple choice questions, see the
section on selecting objects, below.
If you have a multiple-choice question (radio buttons, checkboxes,
dropdown) and you want to reuse the same selections several times, you
do not need to type in the whole list every time. You can define a
variable to contain the list and a
code block that defines the
code to a field makes it a multiple-choice question. The
code itself refers to Python code that generates a list of
possible options for a multiple choice field. The
modifier is used in place of a [
choices] field modifer, which you
would use to specify the choices manually.
The Python code runs at the time the question is asked. Therefore,
you can use the
code feature to create multiple-choice questions
that have dynamically-created lists of choices.
It can be a dictionary (in which case you cannot control the order of items):
It can be a list of text items (in which case the values and labels will be the same):
You can specify a default by including a three-element list where the
third element is
True if the choice should be selected by default.
You can include “help text” for a choice by including a fourth element in one of the lists, where the element contains the help text you want to be available. The user can see the help text by touching the question mark button.
If your code is a list of dictionaries, you can include a
'default' key in the dictionary indicating a true or false value
that represents whether the choice should be selected by default.
Similarly, you can include help text in a list of dictionaries by
'help' key in the dictionary indicating the help text
that should be available to the user.
If you build the list of choices with
code, you can exclude items
from the list using
exclude, where the value of
In this example, the value of
exclude is a single variable. If
given a list of things, it will exclude any items that are in the list.
If you use
datatype: checkboxes, then by
default a “None of the above” choice is added.
You can turn off the “None of the above” choice by setting the
none of the above option to
You can also change the phrase from “None of the above” to something
else, even a Mako expression. Just set
none of the above to the
text you want to be displayed.
If you use
datatype: object_radio, you can use
none of the above in the same way. If the user selects the “none of
the above option,” the variable will not be defined when the user
This option can be useful when you are using the
You can use the
show if field modifier if you want the field to be
hidden under certain conditions. There are three methods of using
show if, which have different syntax.
Using the first method, the field will appear or disappear in the web
browser depending on the value of another field in the
Under this method,
show if refers to a YAML dictionary with two
variable refers to the variable
name of the other field, and
is refers to the value of the other
field that will cause this field to be shown.
This can be useful when you have a multiple-choice field that has an “other” option, where you want to capture a text field but only if the user selects the “other” option.
The second method is like the first, but is for the special case where
the other field in
fields is a yes/no variable. Under this method,
show if refers to the other field’s variable name. If that variable
is true, the field will be shown, and if it is not true, the field
will be hidden.
show if refers to a variable that is itself hidden by a
if, then the condition is considered to be false.
Under the third method, the field is either shown or not shown on the
screen when it loads, and it stays that way. You can use Python
code to control whether the field is shown or not. Unlike
the first method, you are not limited to using variables that are part
fields list; you can use any Python code; however, you
cannot refer to any of the variables that are defined by the current
question. Under this method,
show if must refer to a YAML
dictionary with one key,
code contains Python code.
The code will be evaluated and if it evaluates to a positive value,
the field will be shown.
With all of these methods, if any field is not visible on the screen
when the user presses the Continue button, no variable will be set to
anything for that field; it as if the field was never part of the
This works just like
show if, except that it hides the
field instead of showing it.
Sometimes you might want to do more complicated evaluations with
on-screen variables than you can do with
show if and
When you use the
show if and
hide if field modifiers to refer to
fields that are on the screen, you are able to test whether the fields
are true, or have particular values, but you cannot do anything more
complex, such as test whether the value is one of two values, or
the values of two fields.
js show if and
js hide if features allow you to use any
val() is used to obtain the values of fields. Given the
name of an on-screen field as a string, the
returns the current value of that field.
The field will be shown or hidden whenever any of the variables
expression does not use
val(), it will not be triggered except at
the time the screen loads. Your expression is parsed, but is not
evaluated, when determining what fields your expression references
val(). Thus, if you pass something other than a literal
val(), you may find that the showing or hiding is not
triggered, even though
val() would return the appropriate value.
This works just like
js show if, except that it hides
the field instead of showing it.
disable others is set to
True, then when the user changes the
value of the field to something, all the other fields in the question
will be disabled.
disable others can be set to a list of variables on
the same screen that should be disabled.
The value of
note is Markdown text that will appear on the screen.
This is useful for providing guidance to the user on how to enter
note is by itself as its own “field” in the list of
the text appears along with the other fields:
However, if the
note is used as a field modifier, the note will
appear to the right of field on wide screens. On small screens, the
note will appear after the field:
On wide screens, the location of each
notes is based on the location
of the field itself. This means that if you have
notes on two
adjacent fields, and one of the
notes is lengthy, the
overlap on the screen. Therefore, make sure to keep your notes short.
html is by itself as its own “field” in the list of
HTML will appear along with the other fields:
However, if the
html is used as a modifier for a field, the HTML
will appear to the right of field on wide screens. On small screens,
the HTML will appear after the field:
If you use
no label as the label for your variable, the label will
be omitted. On wide screens, the field will fill more of the width of
the screen if the label is set to
To keep the width of the field normal, but have a blank label, use
"" as the label.
Instead of expressing your labels and variable names in the form of
Label: variable_name, you can specify a label using the
and the variable name using the
If the list of choices for a multiple choice question is empty,
docassemble will try to deal with the situation gracefully. If
there is only a single field listed under
fields, or the question is
a standalone multiple choice question, then the
variable that will be set by the user’s selection will be set to
None, and the question (or the field, if there are other fields
fields) will be skipped.
checkboxes, the variable will be set to an
DADict (a type of dictionary specific to docassemble).
object_checkboxes, the variable will be set to
DAList (a type of list specific to docassemble).
Some datatypes, such as numbers, dates, and e-mail addresses, have validation features that prevent the user from moving to the next page if the input value does not meet the requirements of the data type. The jQuery Validation Plugin is used.
For some field types, you can require additional input validation by adding the following to the definition of a field:
numberdata types, require a minimum value. This is passed directly to the jQuery Validation Plugin.
numberdata types, require a maximum value. This is passed directly to the jQuery Validation Plugin.
minlength: require a minimum number of characters in a textbox, number of checkboxes checked, etc. This uses the jQuery Validation Plugin.
maxlength: require a maximum number of characters in a textbox, number of checkboxes checked, etc. This uses the jQuery Validation Plugin.
You can customize the standard
validation messages that users see. If you want to customize these
messages on a server-wide basis, you can edit the
in the Configuration. If you want to customize these messages on an
interview-wide basis, you can add a
default validation messages
block to your interview. For more information on how to do this, see
the documentation for the
default validation messages block.
You can also customize the messages for a particular field using the
validation messages field modifier.
Each validation error message has a special code. In the example
above, the codes were
max. A full list of these
codes is available in the documentation for the
validation messages field modifier, you can use an abbreviated
version of many of these codes. For example, instead of using the
combobox required, you can use
required. Instead of using
date min, you can use
min. Either will work in the context of a
validation messages field modifier. The last word in the code is
You can also use Python code to validate an
input field. To do so, add a
validate field modifier that refers to
the name of a function that returns
True (or something that
Python considers “true”) if the value is valid, and
something that Python considers “not true”) if the value is invalid.
In this example, the function
is_multiple_of_four is defined as
The error message that the user will see is a generic error message,
“Please enter a valid value.” In most cases you will want to explain
to the user why the input did not validate. To provide a more
descriptive error message, your function can call the
validation_error() function with the error message the user should
In this example, the function
is_multiple_of_four is defined as
This Python code is in the
validationfuncstwo.py file. If 4
does not divide the input value into a whole number, then
validation_error() is called. The
raises an exception, which means that code stops processing once
validation_error() function is called. That is, if
validation_error() is called, the
return True statement will not
The text passed to
validation_error() is the text the user will
see if the value does not validate. If 4 does divide the input value
by a whole number, the function returns
True, which indicates that
the input is valid.
Note that the
validate field modifier is not available for use with
datatype: checkboxes. (However, note that you can use
maxlength to require a certain number of
checkboxes to be checked when
none of the above is disabled.)
A more general limitation of these validation functions is that they can only test for characteristics inherent in the variable being validated; they cannot compare the variable to other variables.
Note that the code under
validation code is not within a function,
so it should not try to
return any values. If the code runs through
to the end, this indicates that the input for the question is valid.
validation_error() is called, or an exception is raised, the
input for the question is considered invalid.
If you have defined a
google maps api key in the Configuration,
you can use the Place Autocomplete feature of the
Google Places API to help your users enter addresses. Address
suggestions will be provided as the user begins to type. To use this
feature, modify the street address (
.address) field by setting
address autocomplete to
For more information on using this feature, see the documentation for
This feature can be used internationally with a variety of address
types. Here is an example that illustrates all of the possible
attributes of the
Address object that can be set by Place Autocomplete.
Sometimes, it is useful for a
question to set a single variable to
True, along with the other variables it sets, much like the simple
“continue” button that sets a variable question does.
If you want your
question to set a variable to
True when the user
presses “Continue,” add a
continue button field line to the
question indicating the variable that should be set to
But what if you wanted to use a variable to refer to an object, such as a person? You could try something like this:
In this case,
tallest_person would be set to the name of the
client or the name of the
advocate. But what if you wanted to
then look at the birthdate of the tallest person, or some other
attribute of the person? If all you had was the person’s name, you
would not be able to do that. Instead, you would want
tallest_person to be defined as the object
client or the object
advocate, so that you can refer to
as you would refer to
You can accomplish this by setting
object within a
fields list, where the
choices are the names of the
objects from which to choose. (Optionally, you can set a
value, which is also the name of a variable.)
Note that this interview incorporates the
which defines objects that are commonly used in legal applications,
advocate. It also contains questions for
asking for the names of these people.
The interview above presents the names of the
client and the
advocate and asks which of these people is the villain.
If the user clicks the name of the advocate, then docassemble will
define the variable
villain and set it equal to
Note that because
advocate is an object,
villain will be an
advocate, not a copy of
advocate. If you
advocate.birthdate, you will immediately be able
retrieve that value by looking at
villain.birthdate, and vice-versa.
villain is an alias, if you refer to
villain.favorite_food and it is not yet defined, docassemble
will go searching for a question that offers to define
advocate.favorite_food. This is because docassemble objects
have an intrinsic identity, a unique name given to them at the time
they are created. (You can inspect this by referring to
villain.instanceName in a question and will see that it returns
advocate.) For more information about this, see the discussion in
the documenation for DAObject. (All docassemble objects are
subtypes of DAObject.)
If any of the objects listed under
lists of objects, such as
PartyList, those lists will be expanded and every item will
be included. You can also include under
choices Python code, such
object presents the list of choices as a
pull-down. If you prefer to present the user with radio buttons, set
object_radio data type
allows the use of a
none of the above option.
By default, the objects listed in the
user interface are labeled by their textual representations. For
example, if the object in a
choices list is an
label for the object will be the textual representation for an
Individual, which is the individual’s name. To use an alternate
label, provide a
object labeler. The
object labeler must be a
Python expression that evaluates to a function.
In this case, the
protagonist and the
antagonist will be labeled
nickname attribute. The
object labeler in this example
is a Python lambda function, which is a shorthand way of creating a
function. You could also used a named function, if you wrote one in a
module. For example, suppose you had some code in a module that
defined the function
Suppose also that you imported this function into your interview using
modules block. Then, in your
fields item you could simply
object labeler: my_labeling_function.
Here is an example that uses
object labeler to label a
object list of addresses.
Instead of writing:
you could instead write:
Address.on_one_line (note the lack of parentheses at the end) is a
reference to the
.on_one_line() method of the
Address class. In
Python, a method is like a function where the first parameter is the
object. So you can call
Address.on_one_line like a function,
passing it the object instance as a parameter.
Using a reference to a method in place of a lambda function only works
if the method has no other required parameters. For example, if your
Individuals and you wanted the the choices to
display as “John Smith’s house,” “Jane Doe’s house,” and “Harry
Morgan’s house,” you could write:
but there would be no way to call this method successfully using a mere method reference like
because there is no place to put the
object labeler works, you can specify a
lambda function that takes the object as its argument and returns help
text associated with a choice. You can also specify an
generator lambda function that generates the image that should be
associated with the choice.
Any variable name referenced in
[FIELD ...] must be one of the
variable names listed in the
fields: list. If a field is referenced
this way in the
subquestion, it will not be displayed the way that
fields are ordinarily displayed, but will be moved into the
subquestion, where it will be formatted differently. Any fields
fields: list that are not referenced in the
will appear on the screen in the normal fashion.
The label of an embedded field is used as the tooltip of the field.
When you are using embedded fields, you can
add the field modifier
inline width to change the initial width of
the field. For example, if you include
inline width: 15em, the
CSS will be altered so that the field is 15em wide. This field
modifier has no effect when embedded fields are not being used.
You can use Python code to generate items inside a
fields. To do
so, simply add an entry under
fields that contains
nothing more). The contents of
code will be evaluated as a Python
For example, if you want the fields to be like this:
you would write this:
Here is an example that asks for the names of a number of people on a single screen:
Note that it is necessary to use the
sets modifier on the question
to manually indicate that the question will define
people[i].name.first. Normally, docassemble automatically
detects what variables a question is capable of defining, but when the
fields are dynamically generated with code, it is not able to do so.
Note also that this example uses the
field method for
indicating the label and the variable name for each field. This is
not required, but it may make field-generating code more readable.
Dynamically-created lists of fields can be paired with
subquestion text that embeds the fields.
It is also possible to mix dynamic fields with non-dynamic fields:
Writing Python code that generates a list of fields can be pretty
complex. This should be considered an advanced feature. Note that
the code above uses the Python function
str() to reduce the
index of a list (which is an integer) into a string, for purposes of
constructing variable names like
If you work with dictionaries (
DADict objects) instead of lists
DAList objects), a useful function is the Python function
repr(), which returns a string containing a string with quotation
marks around it.
For example, suppose you want to replicate this:
You could do something like the following:
The alternative is to try to provide the quotation marks manually,
which can look messier, and then you have to worry about what to do if
key string contains an apostrophe; will that cause a syntax
repr() function takes care of this problem by
producing a robust Python representation of the string.
Here is a lengthy example that illustrates many of the features of
Users can upload files, and the files are stored as a variable in docassemble.
signature block presents a special screen in which the user can
sign his or her name with the trackpad or other pointing device. When
the user presses “Continue,” the signature image will be uploaded to
the docassemble server as a transparent PNG file.
In this example, the
user_signature variable will be set to an
object of type
DAFile. This variable can be included in the same
way that a document upload can be included. For example:
or, if you want to control the width of the image:
On a small screen, users need as much of the screen as possible to
write their signature. For this reason, docassemble will reduce
the size of the navigation bar and put the
question text into the
navigation bar. For this reason, you should make sure your
question text is very brief – no longer than “Sign your name.”
You should also make the
subquestion text as brief as possible.
Although you may be developing your app on a desktop or laptop
monitor, your users are probably using smartphones, so test your app
on a smartphone.
docassemble lets you write a single question that can be re-used throughout an interview.
For example, suppose you want to gather the following variables:
It would be tedious to have to write separate questions for each of these variables.
The special variable
x stands in for any object of type
You can nest iterators up to six levels, using the variables
n, but you have to use them in this order.
For more information about populating groups of things, see the groups section.
For more information about how docassemble identifies what question to ask in order to define a given variable, see the interview logic section.
If you use generic object variable
x, or index variables like
k, etc., it is important that you do not use them in blocks
that you have marked as
Suppose you have a block that defines
docassemble needs a specific value, like
fruit.seeds, it will
find your block automatically, no matter where it is in the interview
source file. docassemble will take care of setting
i = 2 before
“running” your block. Your block will only work correctly if
set to the right value.
If you mark the block as
mandatory in order to force it to be run,
you will be forcing the running of Python code in a context where
the value of
i could be anything; it might be a number like
5, or it might be a string like
'income'. The variable
not even be defined at all.
Thus, you should only use
k, etc. when you are
letting docassemble choose which block to use.
You can allow users to click links or menu items that take the user to
a special screen that the user would not ordinarily encounter in the
course of the interview. You can create such a screen using an
event specifier acts much like
sets: it advertises that the
question will potentially define a variable (although it actually doesn’t).
In the following example, the variable
show_date is never defined;
it is simply sought. The
task_not_yet_performed() function is
used to make sure that the dialog box only appears once.
In the example above, the
event line tells docassemble that this
question should be displayed to the user if docassemble
role_event, which is a special “event” that can
happen in multi-user interviews. The event is triggered when the
interview reaches a point when a person other than the current user
needs to answer a question. For example, while a client is filling
out an interview, the interview logic might call for a variable that
can only be set by an advocate who reviews the client’s answers. In
this scenario, a
role_event will be triggered. When this happens,
docassemble will look for a
code block that
defines the variable
role_event, and it will find the example
event can also be used to create screens that the user can reach
from the menu or from hyperlinks embedded in question text. For
information and examples, see url_action(), process_action(),
action_menu_item(), and menu_items.
event is not appropriate for
questions that set variables
(e.g., that use
etc.). If you want to take the user to a screen that sets a variable,
refer to an undefined variable so that docassemble will seek out
the definition of the variable and show the
question that defines
the variable. Or, if the variable is already defined, use
force_ask(). The interview logic system in docassemble is not
like a flow chart, where you “go to” question 1 and then “go to”
question 2; it is based on seeking definitions of variables and
event modifier can also be used on
code blocks, where the
meaning is similar, but the purpose is not necessarily to show a
review specifier allows interview developers to create a
review screen. A
review screen is type of
question that allows
users to review and edit their answers, whether the user is part of the
way through the interview or all the way through the interview.
Typically, the user will get to this screen by selecting an option
from the web app menu (e.g., “Review Answers”), or by clicking on a
subquestion text (e.g., “to review the answers you
have provided so far, click here”).
Here is an example of a
review screen that is launched from the
If you click “Favorite fruit,” you are taken to a
you can edit the value of
fruit. This has the same effect as
'fruit' or running an action on
'fruit'; whatever block in your interview offers to define
will be used. After the user edits the value of the variable, the
user will return to the
review screen again.
Note that the
review screen does not show a link for “Favorite
fungus” because the variable
fungi has not been defined yet.
fungi is defined, the
review screen would show it.
This behavior is different from the typical behavior of
docassemble blocks. Normally, referring to a variable that has
not yet been defined will trigger the asking of a question that will
define that variable. In the
review screen, however, the presence of
an undefined variable simply causes the item to be omitted from the
In the above example, note that the
question with the
specifier is tagged with
event: review_answers. For more
information about how
events work, see above. The
interview will show this screen whenever it seeks out the definition
of the variable
review_answers. Since the screen is displayed based
event, it can be called as many times during the interview
session as the user likes. Depending on which variables have been
defined, the user will see different things.
You can provide the user with a list of answers the user has provided with buttons that the user can press to revisit an answer:
review specifier, like the
fields specifier, allows you
If these are modified with the optional
show if field modifier, they
will only be displayed if the variable referenced by the
field modifier has been defined. In addition, if any of these entries
refer to a variable that has not been defined yet, they will be
If you include
html as modifiers of an item under the
review specifier, the text will appear to the right of the item on
wide screens. On small screens, the HTML will appear after the item.
You can add
help text to an item, in which case the text is shown
underneath the hyperlink. If this text expects a variable to be
defined that has not actually been defined, the item will not be
shown. Note: this is not available with the
button display format.
By referring to a list of variables instead of a single variable, you
can indicate that more than one variable should be sought. The fields
mentioned will not appear on the
review screen until all have been
If there is a follow-up question that might need to come after the
changing of a variable, you can list the follow-up variable in the
You will need to tag the follow-up question with an
in order for the
review screen to skip the field when it is not
required, it needs to find no
questions that will define the
variable. If the follow-up question is set up in this way, you can
list its variable under
follow up, and docassemble will ask the
question if the
if condition is true, but will ignore the
up variable if the
if condition is false.
You can also indicate more than one variable when using
Some of the variables that you use in your interview might be computed
code based on answers to
questions, rather than defined
directly by asking the user a question. Thus, if the user changes the
answers to these underlying questions, you may want your interview to
recompute the values of these variables. This recalculation does not
happen automatically; however, you can cause it to happen in your
review screen by including
recompute in the list of variables to
In this example, it would not have worked to merely include the
salad in the list of variables, as follows:
Here, the presence of
salad in this list means “ask a
to redefine the variable
salad.” If there is no
salad, the interview will generate an error. Including
salad in a
recompute list, as in the above interview, indicates
that it is ok if the variable is defined by
When you write lists of operations to be performed when a user clicks
a link on a
review page, you will probably want to make sure that at
least one of the variables in the list will trigger the asking of a
question. Otherwise, the user might click the link and be
returned back to the same page again, and when that happens they may
assume that clicking the link didn’t do anything, and the app is
There are three other special commands that you can use in a list of
variables in a
The following example illustrates
This interview demonstrates how to re-do the geolocation of an
Address. When you call
.geolocate() on an
first time, the address is geolocated and the
of the object is changed from
True. If you call
.geolocate() on the object again, the first thing it does is check
.geolocated attribute, and if it is
True, it will immediately
return without doing anything. This is useful for avoiding
unnecessary API calls, which can slow down the responsiveness of your
app. However, if the user edits the underlying attributes of the
address, you need to “reset” the geolocation in order to get it to run
In the above interview, the
set command sets
False, which means that when the
address.county is recomputed, and
.geolocate() method is run again by the
code block, then the
.geolocate() method will actually geolocate the new address.
undefine specifier causes the values to be undefined. The
invalidate specifier works like
undefine, except that the original
values (if any) will be remembered and offered up as default values
question defining the variable is asked again.
In the examples above, the
question containing the
specifier is identified with an
event specifier like
review_answers, meaning that the variable
review_answers does not
actually get defined, though it gets sought.
As a result, a
review screen identified with an
event can only be
shown when triggered by a user action (e.g., clicking a link,
selecting an item from the menu), or with
If you would like to insert a
review screen into the normal course
of an interview, so that it appears to the user one time, you can use
field instead of
In this example, the variable
answers_reviewed actually gets
defined; it gets set to
True when the user clicks “Continue.” It
works much like a standard question with a “Continue” button that sets a
The interview flow in this interview is set by the
First the interview asks about the user’s favorite fruit, vegetable,
and fungus. Then the
review screen is shown. Then the final
screen is shown.
By default, when a
review screen encounters and undefined variable,
it does not seek out its definition. This is so you can have a single
review screen that is used throughout an interview (or a section of
an interview), where the user only sees that fields that have already
been asked about.
If you would like to use the functionality of a
review screen, but
you want all the variables to be defined first, set
This enables you to use tables in your
review screen. Ordinarily,
tables are always undefined (so that their contents always reflect the
current state of the list, so a
review screen would never display them.
By default, the
review screen puts a “Resume” button at the bottom of
the screen. If you want the label on the button to be something other
than the word “Resume,” add a
resume button label modifier.
review is used with
field, a “Continue” button is
used. The “Continue” button can be customized using the modifier
continue button label.
For information about other ways to set a default value for the Continue button label, see the screen parts section.
The list of variables to display to the user in a
review screen needs
to be specified by the interview developer. There are several reasons
why this needs to be done manually as opposed to automatically:
- Variables in your interview may be interdependent. You do not
necessarily want to allow the interviewee to edit any past answer
at will because this may result in internal inconsistencies or
violations of the logic of your interview. For example, if your
interview has a variable called
eligible_for_medicare, which is set after the user answers a series of questions, you would not want the user to be able to go back and set his or her age to 30, at least not without a reconsideration of the definition of
eligible_for_medicare. Therefore, it is important that the interview developer control what the user can edit.
- A list of answers already provided might not be user-friendly unless the interview developer presents it in a logically organized fashion. The order in which the questions were asked is not necessarily the most logical way to present the information for editing.