Customize a Form¶
Forms are highly customizable! Many different fields types are supported, validations can be applied, and everything in the form template down to the field help text and error messages are easily changed.
Each Workflow Action contains a list of form controls and an action map at the
top of the file after the import statements. By customizing the
form_controls
the layout, fields, and actions of a form can be customized.
For a detailed walkthough of creating a new action for a custom Sale Price
approval workflow based on the
SendApprovalFormEmail
action
check out the leisurely start guide.
Create a New Workflow Action¶
The first step to customizing a form is copying one of the existing actions to a new Workflow action file. Because workflow actions are stored in the database, an existing action file cannot be copied to a new file and edited.
One method of creating and registering new workflow actions is to view the file contents from the database and copy them into a new file.
- Open the Extender –> Setup –> Scripts screen.
- Right-click on the script that will be used to build the new action and select View. The action file contents open in a text editor.
- In the text editor, select File –> New.
- Copy the contents of the existing action file to the new file.
- Close the existing file.
- Save the new file with a unique name.
Customize the Form¶
Each workflow action file included with Poplar Forms has a list of form controls defined at the top of the action file. A form control is a widget that displays a field in the form. The standard approval form template looks something like this:
form_controls = [
{
'name': 'APPROVALCOMMENT',
'type': 'textarea',
'label': 'Comments',
'required': True,
}
]
To customize the form, change the contents of the form_controls
variable
to meet your needs.
Need a form with a comment that uses a text field instead of a text area?
Edit the APPROVALCOMMENT
form control to be of type text:
form_controls = [
{
'name': 'APPROVALCOMMENT',
'type': 'text',
'label': 'Comments',
'required': True,
}
]
Users sometimes need a nudge, if you want to tell users up front that the comment is required, add some help text to render with the field:
form_controls = [
{
'name': 'APPROVALCOMMENT',
'type': 'text',
'label': 'Comments',
'required': True,
'help_text': 'Comments are required, please leave one.',
}
]
Because Comments are required, perhaps an initial value is in order to save time in the best case:
form_controls = [
{
'name': 'APPROVALCOMMENT',
'type': 'text',
'label': 'Comments',
'required': True,
'help_text': 'Comments are required, please leave one.',
'initial': 'Approved'
}
]
Adding New Controls¶
Simply define a new element in the form_controls
list to add an additional
control to the form.
What if we need a new form to store the maximum number of widgets that are being approved?
form_controls = [
{
'name': 'APPROVALCOMMENT',
'type': 'text',
'label': 'Comments',
'required': True,
'help_text': 'Comments are required, please leave one.',
'initial': 'Approved'
},
{
'name': 'MAXWIDGETS',
'type': 'integer',
'label': 'Maximum Widgets',
'required': True,
'help_text': 'What is the maximum number of widgets being approved?',
'initial': '5432'
}
]
Where’s the Data?¶
Yes but… where does the data from the new field go? When the
Poller
applies a form of type workflow_approval
(like this one)
all the fields are set as values in the Workflow itself.
So in the case described above, in the steps following the approval wait step,
the MAXWIDGETS
value with be set in the Workflow and can be referenced
as {MAXWIDGETS}
.
Progress To Steps and Form Buttons¶
The buttons displayed at the bottom of the form, and the step that the workflow will progress to when they’re pressed, are passed as the fourth parameter to the workflow action.
They are passed as a comma separated list of button label, progress to step
name pairs. To render three buttons, Allow, Cancel,
Deny that progress to steps Allowed
, Canceled
, and
Denied
, provide the following argument:
Allow=Allowed,Cancel=Canceled,Deny=Denied
Dynamic Initial Values¶
There are three ways to set initial values in the form. The first is to include
the initial
argument to the form control definition at the top of the
action file:
form_controls = [
{
'name': 'mycontrol',
...
'initial': 'my initial value'
}
]
Using this approach, all users of the form will see the same default value, regardless of the state of the workflow or the user accessing the form.
To display a value that changes based on the state of the workflow or views
but is the same for all users, change the call to
create_workflow_approval_form()
to include
the initial value as a keyword argument.
Continuing the MAXWIDGETS
example, the initial value can be set to the MAXWIDGETS
value in the
workflow values by changing the create form call in our custom action:
# Create the form
try:
title, content = render_title_and_content_for(e.resolve(e.p3), e)
form = create_workflow_approval_form(
e.wi.viworkih.get("WIID"),
form_controls,
title,
content,
actions,
MAXWIDGETS=e.wi.getValue("MAXWIDGETS"))
except Exception as err:
showMessageBox("Failed to create approval form: {}".format(err))
return 1
The final approach is to set a different initial value per user. This is done by customizing the URL parameters in the link sent to each user. If we wanted to provide a different initial value to each user, we can do so before the email is sent:
for (username, email_address) in users:
email = Email()
email.setTo(email_address)
if email.load(e.resolve(e.p1)) == False:
error("Unable to load message template '" + e.p1 + "'")
return 1
user_url = "{}?MAXWIDGETS={}&".format(url, user_max_widgets)
email.replace("FORMURL", user_url)
Note
If more than one approach is used to set the initial value of a form control, only one will be applied.
Initial values set in the form control definition are preferred over those set dynamically.
Initial values set when creating the workflow form are preferred over those set in the URL parameters.