Processing List Information
Often times, when you create a WebPart that takes in user entered data, you will need to use information on the page in a process. Processing information from a list section can be tricky because if you want a specific row, you would have to specify which one and if you want all of them, it can be difficult to manage many rows of data.
In our example, we are going to allow the user to select rows of the list section and then send an email to the user for each row selected.
Designing the Feature
When making a change in EASYProcess, it is important to break down the feature into separate requirements. Until this point, you have been following the training steps without knowing what the end result is. Here you are going to think about the feature as if you were taking requirements and planning the change yourself.
We want the user to be able to load our WebPart, choose some rows (some or all), enter their email addres, and have an email per row sent out. This will require:
- Change our List Section so the user can select specific rows
- Allow the user to select multiple rows
- Allow the user to select all rows
- Create a textbox where the user can type in their email address
- Create a button
- The button should pull information from the list section on the page
- Should be able to distinguish a checked row versus an unchecked row
- Pull the user’s email from the page
- Send an email out to the user for each row that is checked
Row Selection Mode and Select All
The List Section that we created actually has a Row Selection property.
Change the “Row Selection” property to "Multiple" and the “Show Select All” property to "True" as shown below.
- None: no checkboxes will display
- One: Checkboxes will display next to each row and only one can be checked
- Multiple: Checkboxes will display next to each row and multiple can be checked
Show Select All
- True: A checkbox will appear that when selected, it checks all the checkboxes of the list section. This will be a “Select All” feature so the user doesn’t have to individually check each line.
- False: No “Select All” feature will be present.
Create Button and Attach a Process
Create a new section under the list section and put a button in it. Fill out the below button properties and rename your newly created section to be meaningful.
Section Description: Email Actions
Button Name: EmailSelected
Button Text: Email Selected
You can attach a process to this button by double clicking the gear on the right side of your button.
Our button process is going to retrieve the information from the list section and then process that information to perform an action. This requires us to pull the information from the list section for use in the button process.
Once you’re in the newly created button process, find the “GetFieldValues” under the “HTML Services” Workshop in the Services list. Drag it onto the Process Canvas and connect it like shown.
This service is used to pull values from fields on the page. Click into the “GetFieldValues” service to configure it.
- SectionId - Enter the section id of the list section. You can find this in the WebPart canvas by clicking on the list section and looking in the right panel in the SectionId property.
- RowIndex - Leave this blank for now. We want all the rows of the list section, so we shouldn’t specify a row index here.
- SelectedRowsOnly - Drag “True” from the right under “Valid Values”. Since the List Section’s Row Selection is turned on, this will only return to us, the selected rows.
- Fields - Right click and add a field. Drag from the left panel “ABAN8” into the “FieldName” property. Again, leave the RowIndex blank.
GetFieldValues doesn’t really require that we specify Fields as long as we provide the SectionId. If you give a SectionId, it will return all the fields in that section. However, if you want to filter the fields returned, you can specify fields and it will return only those. We are going to practice filling in each field we want returned as practice.
In our example, we are using GetFieldValues with a List Section, but it can be used with a regular Section too. The fields again do not need to be specified, but can be to filter the number of fields returning.
You could create each field by right-clicking to create a field and draggin the field from the page on the left, or you could use the EASYEdit Tool and type the values in if you find it faster. Right-click the “Fields” node and click “EASYEdit Fields”.
The EASYEditor is a useful tool if you just want to type out all the values you want. In order to create all the columns for the labels in the list section, match screenshot below. After reading the instructions in the EASYEditor you may notice that this tool would not be helpful if the data you wanted to put in the properties contained commas or new line characters. This is important to remember, but for our use, that won’t be a problem.
When you are done, your service should match the screenshot below. Also remember that your SectionId is going to be different.
So far all our button will do is return the rows from the page which are selected, but let’s test that functionality. Return to the WebPart Canvas and navigate to the “Test” tab. Select some rows, click the button, and look at the logs.
You’ll notice some columns were returned that you didn’t specify. “EP_RowSelect” is one of them. This column returns either “True” or “False” and it maps to the checkbox for the Row Selection of the List Section. This will be how we can tell if a row is selected and an email should be sent. This would be returned even if we didn’t specify to only return selected rows. So alternatively, we could have requested every row to be returned and then only taken action on the ones that have EP_RowSelect = “True”.
Now we know the GetFieldValues service is working. Before continuing, remember to rename the GetFieldValues service. Since services are referenced by their name, if we wanted to change the name later on, we would need to rename all the references in other services. Rename the service “ListofAddresses”
Create a For Each Loop
Next, we want to send out an email for each selected row. We can do this with a For Each Loop. This can be created a few ways. The first is by finding the services in the services list and dragging them onto the Process Canvas. The services we will need are “For Each” and “End For Each” which can be found in the “Process Flow Elements”.
The other way to create the For Each loop, is to right-click the service we want to For Each Loop on and select “Create ForEach Loop”. This is sometimes more useful because it will auto-name the services and configure the service for you.
After creating your For Each services, the Process Canvas will resemble the screenshot below.
You’ll notice that whether created by either method, the name of the beginning service matches the name of the end service. These services must be used in pairs and EASYProcess knows which ones are the corresponding pair based on the naming scheme.
How does the For Each service work?
For Each loops will automatically index the path specified in the SelectorValue input of the ForEach loop.
Consider the output from our ListofAddresses service. Each record has a path of WorkData/ListofAddresses/ABAN8.
Lets define WorkData/ListofAddresses as the selector value for the For-Each loop. (Which is already done for you if you created the For Each service by right-clicking the service.)
Now if we try to access WorkData/ListofAddresses/ABAN8 (or anything that has that selector path) in any services between the start and end of the for each loop, it will automatically index the path based on the current index counter of the loop.
So on the first iteration, WorkData/ListofAddresses/ABAN8 will become WorkData/ListofAddresses/ABAN8 which will access the first node of the selector path.
On the second iteration, WorkData/ListofAddresses/ABAN8 will become WorkData/ListofAddresses/ABAN8 and so on…
Send an Email Based on the Data Retrieved From the WebPart
Now, add a SendEmail service between the ForEach and EndForEach. We're going to send 1 email for each row returned from the page with information about that person.
Change the properties of the SendEmail service as below.
- For now, hard code this to yourself so you can verify this is being sent out.
- Drag and drop the output of the list service So it reads as below
- “Address Information for [Name]”
- Do the same thing as the subject, but Make it read:
- “[Name] ( [AddressNumber] ) from Branch [Branch] has an address of [Address] and it has been effective since [Effective Date]”
You can test the WebPart at this point to make sure the SendEmail service is configured, but remember, right now it sends out an email for every row, regardless of the user’s selection.
Understanding Binary Decisions
So far all of our Processes have had only one process flow, meaning the same thing happens each time it runs. We are going to make this process a little different by adding a Binary Decision. This is a service that asks a question and depending on the answer, directs the process to one way or the other.
The Binary Decision service is configured by defining one or multiple tests. A test is a comparison of two value. You give it one value and compare it to an expected result. For example, if we want our Binary Decision to ask “Is this row checked?” our test would compare the WorkData/ListofAddresses/[SectionId]_Select = “True”.
The Binary decision performs the test and outputs either “True” or “False”. This directs the process flow either to the right or down depending on the result of the test.
Each test is composed of a Left Clause, a Right Clause, and the Operator. Typically this is how that string is broken down into the Binary Decision inputs:
The above example is a Binary Decision with one test. If the Left Clause is equal to the Right Clause, the Binary Decision returns “True”.
Each Binary Decision can contain one or many tests. Each test is separated by an AND/OR operator, which determines the order in which the tests are run. ANDs are always evaluated before ORs. The following diagram explains how multiple tests are handled.
Add Logic to Only Email If Row is Selected
Previously, when we set up the GetFieldValues service, we specified to return only the selected rows. So we could count on that service returning only the records we want to send emails for, and only having the SendEmail service inside the For Each loop. However, for this example, set the “SelectedRowsOnly” property of the “GetFieldValues” service to “False” so we can iterate through all rows on the page in the list section, and only send out an email for some of them.
Use the Binary Decision service to match your Process Canvas to the image below.
Configure your Binary Decision like so. When this test is “True”, the answer to the question “Is this row checked?” will be “Yes” and the email will be sent out.
Test the Email
Now test the web part and click the Email button. It should send 1 email for each row seen on the page (It doesn't send it for the hidden rows).
You should have gotten one email for each selected row of the list section. If you click the “Select All” box, you should receive 10 emails.
Deselect the Rows
You may have noticed, after you sent out the emails, nothing changed on the page; the rows were still selected. This is because we didn’t tell the page to refresh or the rows to uncheck. Refreshing the page would be an easy fix, but let’s say the user had paged through the list section and we wanted to preserve that, which would be lost on a page refresh. Instead, we really just want the rows to be deselected now.
To fix this, at the end of your for each loop, add a service “SetRowSelection” from “HTML Services”. Configure your service like below.
- SectionId - Set this to the List Section Id
- SelectAll - Set this to “False”
- Rows - Although you could add rows to target specific rows by their index, leave this blank. This will target all rows, which is what we want.
Test again and notice that after the button is clicked and the emails are sent, the rows will be deselected.
Button Click Animation
Since the processing in your email button could take a while, we want to try to give the user a notice that the button is processing the information. We also want to stop the user from clicking the button multiple times.
You can achieve this through properties of the button itself.
Under the “OnSubmitProgress” section of the button properties, there are three properties:
- Display Progress Animation - Options are True/False. When True, False, there is no additional animation when the button is pressed.
- Progress Animation Image - If nothing is entered here, but DisplayProgressAnimation is turned on, the default image will show. This is the spinning wheel.
- Progress Animation Text - Text can display beneath the image to inform the user of how long it should take or what is happening. If left blank, no text will display.
Let's change the “Display Progress Animation” property to "True" and the “Progress Animation Text” to "Sending Emails..."
Now if you test your email button, you should get an animation similar to below.
Using the User’s Email
We now know the SendEmail service works. Now we can add the feature where the user can enter their email in a textbox and use that entered email in the process.
In the same section you created your button in, add a textbox. Configure your text box with a name so it is meaningful to you and a description so the user knows what should be entered in the text box on the page.
TextBox Description: Email Address
TextBox Name: EmailAddress
We also want to add a feature where the user can just enter their email address and hit the enter key to press the button. To do this, we need to tell the textbox which button to press when the user does this. This is controlled in a property of the TextBox called “DefaultButton”. Set the DefaultButton property to the name of the button as you see it on the WebPart canvas.
We are now going to edit the button process. We need to pull the user-entered email address from the page for use in our process. We have already done this with our list section, but now that we are beginning to add more fields from the page, it may be a good idea to create a new reference at the beginning of the process to store all the variables used from the page.
It is good to get in the habit of doing this so that when you develop features that pull many values from the page, in the future if a label or a textbox’s name changes, you will only have to change the reference in one place instead of many.
Drag an “Evaluate” service out from under the “String/Math Operations” and name it “Prevalues”. Configure this Evaluate to have one Eval with a Name of EmailAdddress and an Expression with the variable pointing to the field on the page.
Now, change your SendEmail service’s “To” parameter to use this reference.
Test your send email service again by this time typing in your email address before selecting the rows and clicking the button. Test clicking into the textbox and hitting the Enter key to press the button.
Export to Excel
The List Section has a property called "Data Download" under the List Mode properties.
Change the value of this property to "CSV" and it should show a little export to excel button above your list as shown below.
The fields in the list section all have a property called “DownloadMode” This determines whether that field will display on the WebPart as well as be visible in the downloaded CSV. All of our Labels should have “Display and Download” selected so that each field that is displaying on the WebPart will also be available in the downloaded CSV. Change all the fields to have this value.
Now, go to the “Test” tab of the WebPart. Notice the new icon in the top left of the list section. If you click this, it should download the current list into a CSV file.
Open the CSV and confirm all the columns are present. Experiment by changing some of the labels to Display Only or Download Only and download the CSV again to see how it changes based on the selection.
We will discuss error handling in depth at the end of the training, but for now, we want to catch two error cases that we know users will encounter: not typing in an email address, not selecting any rows, and accidentally selecting the wrong rows. These are some user error cases that we can catch with some modification to our button process.
No Email Address Entered
Since we are using an “Evaluate” service named “Prevalues”, any time we want to reference a value from the page, we should reference it in the Prevalues Evaluate. Create a binary decision that asks “Is the email textbox blank?”.
Remember you can right click a Binary Decision to swap the “Yes” and “No”. If the email is blank, direct it to a service “SetTerminateActions” from “HTML Services”. In this service you can specify a message to show to the user.
This service is used for actions that will be executed when the process finishes. We are using it here to show a message to the user, but it could be used to redirect the user to a new page or refresh the current window. This service may come in handy later with other error handling and future projects.
No Rows Selected
If the email was not blank, we want to continue on to our next case; the user did not select any rows. For this, let’s change the “SelectedRowsOnly” property of “GetFieldValues” to True again. We only want the selected rows to return so it’ll be easier to check if any were selected. Drag another Binary Decision onto the process canvas and configure it like below.
If none are selected, this node will not exist. This binary decision is performing an existence check. EASYProcess makes this easy with the “*EXISTS” option in the right clause. If you run it while in the service canvas, you’ll notice in the logs that the actual test looks a little different. Here it is below.
In order to perform the actual existence check, all it really needs to do is set the test equal to the node. If “True” returns, this node exists. If “False” returns, it does not.
After your Binary Decision, add another SetTerminateActions service to show the user a message when no rows are selected.
User Selected the Wrong Rows
Our last error case is the user selected the wrong rows. There isn’t much we can do about this one, but we can ask the user if the selection is correct. Add a “UserDialog” service from “HTML Services”. Match your service to the screenshot below.
This service can be used to display a message to the user and provide buttons with options. In our example, we are asking the user if they really want to send out a certain number of emails. We added an XSLT variable with a “count” function in it to make that number of emails dynamic. We also created two buttons: Yes and No. In our example, the label on the button matches the value which is associated to it. When the user clicks a button, this service will have a chosen response which will be the response associated with the button which was clicked. For this reason, this service is always used in combination with a Binary Decision. Add a Binary Decision below this service that checks which option the user chose. You can be more creative with your button labels if you want, but keep the responses simple since those are the values we will be testing for.
If the user was not sure, we can end the process. There is no need for further action, we can just stop the process which will preserve the state of the page and let the user re-evaluate the selections.
Error Handling Overview
Here is all the error handling once it is complete. You’ll notice this added a lot to our process. Often times, the feature you are developing will be rather small, but the error handling for it will allow you to think about all possible cases, not just the successful case. This is an important step to development and the added effort will improve the user experience.