In this example, I'm going to create a color-picker custom control for Nintex Forms On Premises 2013. The color-picker control implements the HTML5 color input and illustrates how you can bind your own control using the Nintex.Forms.Sdk.dll to Microsoft SharePoint with Nintex Forms. It also demonstrates how to store and retrieve data to and from your control.
Color Picker Control
The color picker has the advantage of only using a single HTML5 tag, <input type="color">. However, it has the big disadvantage of being an HTML5 tag not supported by Microsoft Internet Explorer. IE is the only browser that runs the Nintex Forms Designer. This means that when you design your form with the color picker in IE using the Forms Designer, you will need your users to interact with the form in a different browser that supports the tag. The color control is supported by Google Chrome, Mozilla Firefox, and Apple Safari. For a production-worthy implementation of a color picker you would naturally want one that actually works with IE, but this should work fine for walking through the basics of creating a custom control.
For an implementation of a custom control that does work with IE, check out the code sample for a range control using a JavaScript Library and CSS styling in the Nintex Forms Software Development Kit (SDK).
An overview of the steps used to create the control
I created the control as a HTML page using a single input tag in order to isolate the HTML element and experiment with its behavior. This was perhaps overkill for a single line of HTML, but if you're creating a more complex control dependent on JavaScript and cascading style sheets (CSS) it is probably prudent to work out the control interaction in an HTML and JavaScript work-space before you build your managed code solution in Microsoft Visual Studio.
You can think of a custom control as a very tiny web page. It is a page that can be 150 pixels by 75 pixels wide. You can build interaction using HTML, CSS, and your favorite JavaScript libraries such as JQuery, D3.js, React.js, and so on. Actually, you can use any technology that you can wire up to your custom class, but HTML is readily accessible by C#. This solution, and the code sample in the SDK, read and write the the value of the control by using the HTML DOM.
At a more abstract level, your control is an isolated bit of interaction that takes in user interaction -- such as mouse clicks, list selections, and keyboard input -- and converts that input into data that will be meaningful to SharePoint. That is, it is data that can be stored in a SharePoint list. In turn, the control can read that data from the SharePoint list and apply the value to the control. In this example, the color picker generates the hex value color value of an RGB color selected by a form user, and then stores that value in a SharePoint list, in a text field, as a string. When the control loads, it checks if there is a value in the bound text field and then applies the value to the control.
MyCustomColorPicker Control Interaction
When I open the Red record, the solution loads the text field value in the color column for red, here #ff0000, and the color picker displays the value.
If I want to edit the record, I click edit item, and then click control to open a color picker.
I can then use the color picker to select any color in the RBG color space.
After I save the record, the new value, #ff80ff, is stored in persistent storage in the color column of the SharePoint list.
This should make it clear what you should expect provided you are using a browser with color picker support. That brings up an issue with custom controls: they may behave differently than expected on different browsers and in different context. So like any prudent software developer, you'll need to test your code and its performance in the context in which you expect your users to interact with your form.
So, how did I build this control?
Building the Control
The steps I followed:
- I used the instructions for deployment and creation of a custom sample in the Nintex Forms SDK as my general process.
-
I created an empty SharePoint 2013 Project in Microsoft Visual Studio 2015 and added the dependencies. In particular I used the Nintex.Forms.dll and Nintex.Forms.Sdk.dll. With the most recent update to Nintex Forms On Prem 2013, you can find the new Nintex.Forms.SDK.dll in the Global Assembly Cache (GAC) on your server hosting Nintex Forms.
- I refactored and simplified the classes in the sample, which I will talk about below. You can find the code sample at the end of this topic.
- When Visual Studio gave my code a clean bill of health, I built and deployed my solution as a farm solution. Visual Studio deploys and activates your wsp file in one fell swoop. You will also be able to retract your solution with a single click. This is really handy if -- like me -- you find yourself deploying and retracting a half dozen times as you get your solution into order.
- I then added the solution DLL to the General Assembly Cache (GAC), and manually constructed the string used to register the custom control to the Nintex Forms Manager.
- Finally, I created a form in the Nintex Forms Designer, verified that my control showed up in the Custom Controls group in the control toolbar, added the control to the surface of my form, and bound the control to a text field, in this case the Color column in my SharePoint list.
MyColorPickerControl and MyColorPickerControlProperties.cs
So to walk through the class files:
Unlike the CustomSlider Control, I'm not using any JavaScript or CSS with this control.
The base html is:
<input type="color" value="#ff80ff">
The input type color represents a color well control, for setting the element's value to a string representing a simple color. It contains some of the following attributes:
- Autocomplete
In this case we are leaving at default and do need to set this attribute. - List
This is an ID attribute which can be used to identify the element n the HTML DOM. - Name
This is the name attribute which can also be used to identify the element in the HTML DOM. - Value
This is the value held by the control. This is the key attribute we will be working with.
These properties are reflected in the MyColorPickerControlProperties class, where you can see that I am just using the value attribute.
The bulk of work is done by the MyColorpickerControl class.
To begin, let's look at the code used to create the line of HTML. MyColorpickerControl.CreateColorPickerComponent() creates an HTMLGenericControl object.
private HtmlGenericControl CreateColorPickerComponent()
{
var picker = new HtmlGenericControl("input");
picker.Attributes.Add("type", "color");
picker.Attributes.Add("value", ColorPickerProperties.StartValue.ToString());
if (ReadOnly)
{
picker.Attributes.Add("disabled", "disabled");
}
return picker;
}
The control is wrapped in a DIV. This is not necessary, but I think helps determine the boundaries of your custom control.
private HtmlGenericControl CreatePickerWrapperComponent(HtmlGenericControl pickerComponent)
{
var wrapper = new HtmlGenericControl("div");
wrapper.Attributes.Add("id", Path.GetRandomFileName().Replace(".", "));
wrapper.Attributes.Add("style", "width:80%;");
wrapper.Controls.Add(pickerComponent);
return wrapper;
}
The Control label is created by MyColorpickerControlCreateDisplayValueComponent().
Now lets turn to the method that constructs the entire control:
protected override void CreateFormControls()
{
ColorPickerComponent = CreateColorPickerComponent();
ColorPickerWrapperComponent = CreatePickerWrapperComponent(ColorPickerComponent);
DisplayValueComponent = CreateDisplayValueComponent();
Controls.Add(ColorPickerWrapperComponent);
Controls.Add(DisplayValueComponent);
// Set name attribute after adding it to the control hierarchy so we have the finalized client id
ColorPickerComponent.Attributes.Add("name", ColorPickerComponent.ClientID);
}
So this creates your control, but there are few other things to point out in the sample.
Your control leverages an existing control from the set of control in the Nintex.Forms. You can access the Nintex.Forms via the Nintex.Forms.SDK. Your control class is derived from NintexFormControl. This means you can use the Basebindable class to create a bindable control.
Your control leverages the textbox control in the Initialize method:
SupportedFormControlTypes = new List<FormControlType> { FormControlType.SingleLine };
With this set, you will be able to bind the control to a SharePoint list column. In our example, the control is bound to the Color column, which is a text column.
Finally, we need to get data into the control value and out of the control value and into the column. This is handled with the two methods.
Input (line 69). This reads the value of the color picker from the HTML DOM.
protected override object GetUpdatedValue()
{
String value;
value = Page.Request.FormeColorPickercolComponent.ClientID];
return value;
}
Output (line 62). This sets the value of the color picker by updating the controls value attribute.
protected override void OnFormControlDataBinding(object sender, EventArgs e)
{
EnsureChildControls();
var value = GetValue();
ColorPickerComponent.Attributesr"value"] = value.ToString();
}
So for good measure lets walk through the file in a linear fashion. MyColorPickerControl is derived from the NintexFormControl. You can find more information about the classes for creating controls in the Forms SDK .NET Class Reference library.
Properites
The MyColorPickerControl class includes:
- FormControlTypeUniqueId
A unique ID using the .NET Guid. I generated this using the Guid tool in Visual Studio. - FormControlPropertiesComponent
This is an HTML object that represents the control. - ColorPickerWrapperComponent
This is the DIV that wraps the control. - DisplayValueComponent
This defines the control label. - MyColorPickerControlProperties
The property maps to the attributes in the control.
Methods
The MyColorPickerControl class includes:
- OnPreRender
At the prerender event, add the scripts and CSS. - GetCanvasDesignTimeHtml
Adds the HTML for the Froms Designer. - CreateFormControls
Constructs the forms control and establishes the clinet ID (referenced when retrieving the value of the control). - GetDefaultFormPropertiesProtected
Retreives the form control properties. - Initialise
Establishes the properties of the control used in the Form Designer, such as the name, description, control group, and re-size flag. It also overrides the SupportFormControlTypes used to base the control on the BaseFormControl. This used to establish the control as a bindable control linked to a form control type. In this case it is a SingleLine control, which is a text box control that holds string values. - OnFormControlDataBinding
Sets the value of the color picker by updating the controls value attribute. - GetUpdatedValue
Reads the value of the color picker from the HTML DOM. - CreateColorPickerComponent
Creates the HTML for the control. - CreatePickerWrapperComponent
Creates a DIV to wrap the control. - CreateDisplayValueComponent
Creates the label for the control. - RegisterColorPickerPackage
Adds the scripts and CSS. - AddPickerScripts
Adds the scripts for the control.
Summary
The control is created by overriding the BaseFormControl and then adding your HTML with styles and JavaScript extensions. The control package is registered and given an ID, and then deployed to your server farm.
Code Sample
The control uses two classes.
MyColorPickerControl.cs
MyColorPickerControl is derived from the NintexFormControl and used to build the control.
namespace MyCustomColorPicker{ using System; using System.Collections.Generic; using System.IO; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using Nintex.Forms; using Nintex.Forms.FormControls; using Nintex.Forms.Sdk; public class MyColorPickerControl : NintexFormControl { /// A unique ID using the .NET Guid. I generated this using the Guid tool in Visual Studio. public override Guid FormControlTypeUniqueId => new Guid("A0B7071D-633A-4C60-BA9C-7778E16C373D"); /// This is an HTML object that represents the control. private HtmlGenericControl ColorPickerComponent { get; set; } /// This is the DIV that wraps the control. private HtmlGenericControl ColorPickerWrapperComponent { get; set; } /// This defines the control label. private Label DisplayValueComponent { get; set; } /// The property maps to the attributes in the control. public MyColorPickerControlProperties ColorPickerProperties => (MyColorPickerControlProperties)FormControlProperties; ///At the prerender event, add the scripts and CSS. protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); RegisterColorPickerPackage(); } ///Adds the HTML for the Froms Designer. public override string GetCanvasDesignTimeHtml(FormControlProperties properties) { return "<input type='text' value='a color picker'></input>"; } ///Constructs the forms control and establishes the clinet ID (referenced when retrieving the value of the control). protected override void CreateFormControls() { ColorPickerComponent = CreateColorPickerComponent(); ColorPickerWrapperComponent = CreatePickerWrapperComponent(ColorPickerComponent); DisplayValueComponent = CreateDisplayValueComponent(); Controls.Add(ColorPickerWrapperComponent); Controls.Add(DisplayValueComponent); // Set name attribute after adding it to the control hierarchy so we have the finalised client id ColorPickerComponent.Attributes.Add("name", ColorPickerComponent.ClientID); } ///Retreives the form control properties. protected override FormControlProperties GetDefaultFormPropertiesProtected() { return new MyColorPickerControlProperties(); } /// Establishes the properties of the control used in the Form Designer, such as the name, description, control group, /// and re-size flag. It also overrides the SupportFormControlTypes used to base the control on the BaseFormControl. /// This used to establish the control as a bindable control linked to a form control type. In this case it is a /// SingleLine control, which is a text box control that holds string values. protected override void Initialise() { DisplayName = "My Color Picker"; Description = "This is a custom color picker control"; GroupName = "Custom Controls"; DefaultCanResizeAtRuntime = true; SupportedFormControlTypes = new List<FormControlType> { FormControlType.SingleLine }; } /// Sets the value of the color picker by updating the controls value attribute. protected override void OnFormControlDataBinding(object sender, EventArgs e) { EnsureChildControls(); var value = GetValue(); ColorPickerComponent.Attributes "value"] = value.ToString(); } /// Reads the value of the color picker from the HTML DOM. protected override object GetUpdatedValue() { String value; value = Page.Request.FormtColorPickerComponent.ClientID]; return value; } /// Creates the HTML for the control. private HtmlGenericControl CreateColorPickerComponent() { var picker = new HtmlGenericControl("input"); picker.Attributes.Add("type", "color"); picker.Attributes.Add("value", ColorPickerProperties.StartValue.ToString()); if (ReadOnly) { picker.Attributes.Add("disabled", "disabled"); } return picker; } /// Creates a DIV to wrap the control. private HtmlGenericControl CreatePickerWrapperComponent(HtmlGenericControl pickerComponent) { var wrapper = new HtmlGenericControl("div"); wrapper.Attributes.Add("id", Path.GetRandomFileName().Replace(".", "")); wrapper.Attributes.Add("style", "width:80%;"); wrapper.Controls.Add(pickerComponent); return wrapper; } /// Creates the label for the control. private Label CreateDisplayValueComponent() { var displayValue = new Label(); displayValue.Attributes.Add("style", "float:right; width:20%; position:relative; left: 5px; top:-20px;"); return displayValue; } /// Adds the scripts and CSS. private void RegisterColorPickerPackage() { AddPickerScripts(); } /// Adds the scripts for the control. private void AddPickerScripts() { Page.ClientScript.RegisterClientScriptInclude(GetType(), "jquery", "https://code.jquery.com/jquery-2.2.0.min.js"); var startupScript = @" $(document).ready(function(){ var $picker = $('#" + ColorPickerComponent.ClientID + @"'); });"; Page.ClientScript.RegisterClientScriptBlock(GetType(), $"pickerStartup_{ColorPickerComponent.ClientID}", startupScript, true); } }}
MyColorPickerControlProperties.cs
MyColorPickerControlProperties is derived from the NintexFrom ControlProperites class and contains configuration values and attributes of the control.
namespace MyCustomColorPicker{ using System; using System.Runtime.Serialization; using Nintex.Forms; using Nintex.Forms.Sdk; Serializable] DataContract] public class MyColorPickerControlProperties : NintexFormControlProperties { public MyColorPickerControlProperties() { StartValue = "#F4A460"; } DataMember] ControlPropertyInfo( DisplayName = "Start Value", Description = "...", ChangeAction = ControlPropertyChangeActionType.RefreshFromServer, GroupName = NfConstants.CommonResourceStringNames.ControlPropertyGroupGeneral, DisplayOrder = 90001)] public String StartValue { get; set; } }}