In the past I’ve created custom workflow activities for SPD (SPD Workflow activity - Copying a listItem accros a site & SPD Workflow activity - Creating a document library) and now the time came to develop some activities for Nintex Workflow! Basically it’s just the same as building a activity for SPD only with Nintex you also need to include some other things like
- UI page, so that users can configure your activity.
- GenericRenderingAdapter, this sits between the UI page and the Activity itself.
To get all the details about this I can recommend to download the Nintex SDK and find out for yourself how this all works. This post is about what I couldn’t find in the SDK ;)
The activity will set an alert to a specific list for a specific user. So to do this I need two controls, a dropdown that holds all the lists from the current web and a PeoplePicker.
- Dropdown <asp:DropDownList ID="uxLists" runat="server” />
- PeoplePicker <Nintex:UserChooserWebControl id="uxUser" multiselect="false" SelectionSet="User" AllowExternalEmailAddresses="False" runat="server" />
The first thing to keep in mind, is the getting and setting of the properties of your activity is done using javascript. In general, every Nintex page has the following two javascript functions where you get and set the values of the controls on the page : “TPARetrieveConfig” and “TPAWriteConfig” .
Here is how the “TPARetrieveConfig” looks like:
function TPARetrieveConfig() {
//Get the selected item from the Config Store
var listNameOrId = configXml.selectSingleNode("/NWActionConfig/Parameters/Parameter[@Name='ListGuid']/PrimitiveValue/@Value").text;
//Get a reference to the DropDownList
var uxLists = document.getElementById("<%= uxLists.ClientID %>");
//Set the DropDownList 'selected' item to the stored value
uxLists.value = listNameOrId;
if (uxLists.selectedIndex == -1) {
// its a newer action where the title instead of the id is stored
for (var x = 0; x < uxLists.options.length; x++) {
if (uxLists.options[x].text == listNameOrId) {
uxLists.selectedIndex = x;
break;
}
}
}
//Defining a new function to retrieve the stored value and setting the PeoplePicker
var getUsers = function() {
if (configXml.selectSingleNode("/NWActionConfig/Parameters/Parameter[@Name='PrimaryUser']/PrimitiveValue/@Value") != null) {
setPeopleEditorDisplayText("<%= uxUser.ClientID %>",
configXml.selectSingleNode("/NWActionConfig/Parameters/Parameter[@Name='PrimaryUser']/PrimitiveValue/@Value").text);
}
}
//This bit is very important, if you don't do this the value of the control will be empty
window.attachEvent("onload", getUsers);
}
And here is how the “TPAWriteConfig” looks like :
function TPAWriteConfig() {
//Setting the ConfigStore with the selectedItem of the DropDownList
configXml.selectSingleNode("/NWActionConfig/Parameters/Parameter[@Name='ListGuid']/PrimitiveValue/@Value").text = document.getElementById("<%= uxLists.ClientID %>").value;
//Setting the ConfigStore with the selected and validated user
EnsurePrimitiveValueNode(configXml, "PrimaryUser");
peopleEditorCheckNames("<%=uxUser.ClientID %>")
configXml.selectSingleNode("/NWActionConfig/Parameters/Parameter[@Name='PrimaryUser']/PrimitiveValue/@Value").text = getUsersFromPeopleEditor("<%=uxUser.ClientID %>");
return true;
}
With this markup it will be rendered as if it was a out-of-the-box Nintex Activity ;)
<asp:Content ID="ContentBody" ContentPlaceHolderID="NintexPropertyPlaceHolder" runat="Server">
<div class="RowBlue">
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td valign="top">
<span class="label req">
Select List
</span>
</td>
<td valign="top" class="inputWidth" style="width: 340px;">
<asp:DropDownList ID="uxLists" runat="server"/>
</td>
</tr>
</table>
</div>
<div class="RowBlue">
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td valign="top">
<span class="label req">
Primary Owner
</span>
</td>
<td valign="top" class="inputWidth" style="width: 340px;">
<Nintex:UserChooserWebControl
id="uxUser"
multiselect="false"
SelectionSet="User"
AllowExternalEmailAddresses="False"
runat="server"/>
</td>
</tr>
</table>
</div>
</asp:Content>
That’s it.. and for me, to get and set the values of the controls on the dialog page actually was the hardest part.
I’m currently investigating how to re-use the CredentialControl to create activities that can be used with ‘elevated’ permissions, that would be nice eh? ;)