Article Customizing the Rendering of Individual Configuration Options

Many plugin types support exposing configuration options (for example, IConfigurablePlugin ). Configuration options can make use of shared property templates that cover many configuration needs. If a plugin exposing configuration needs a custom rendering of a property, it can host its own property templates.

When would I want to implement a custom property template?

Verint Community includes rich built-in user interfaces for dynamic configuration property data types with options that cover many cases. Additionally, shared property templates  are included that support some special cases. When defining configuration for a plugin that requires a unique user interface that is not covered by these existing templates, a new custom template can be rendered by the plugin supporting configuration.

Implementing a Custom Property Template

Generally, plugin types exposing configuration options also have an extension interface that enables it to host custom property templates that can be used by its parent plugin type. For example, IConfigurablePlugin (v2) has an extension interface called ITemplatableConfigurablePlugin (v2) that allows the configurable plugin to render one or more of its configuration options using a custom property template. These extension interfaces generally expose two methods: PropertyTemplateExists() and RenderPropertyTemplate().

The PropertyTemplateExists() method is called to determine if a specific template name is supported by the plugin (if not, shared property templates will be reviewed for the named template). For example if we only had one property template defined in the plugin named "mypropertytemplate", the method could be implemented as:

public bool PropertyTemplateExists(string templateName)
{
    return templateName == "mypropertytemplate";
}

Then, when the plugin exposes a configuration property and sets its Template property to "mypropertytemplate", Verint Community will know that the plugin is going to render a custom UI for this property.

The rendering of the property template's client-side representation is implemented via the RenderPropertyTemplate() method. 

public void RenderPropertyTemplate(string templateName, System.IO.TextWriter writer, IPropertyTemplateOptions options)
{
	if (templateName != "mypropertytemplate")
		return;

	var value = options.Value?.ToString();

	var messages = new string[]
	{
		"Hello, how are you?",
		"Hey, how is it going?"
	};

	for (var i = 0; i < messages.Length; i++)
	{
		var id = options.UniqueId + "_option" + i;
		var selected = messages[i] == value ? @" checked=""checked""" : string.Empty;
		writer.Write($@"
			<div>
				<input type=""radio"" value=""{messages[i]}"" id=""{id}"" name=""{options.UniqueId}""{selected} />
				<label for=""{id}"">{messages[i]}</label>
			</div>
		");
	}

	writer.Write($@"
		<script type=""text/javascript"">
		$(function() {{
				var api = {options.JsonApi};
				var options = $('input[type=""radio""][name=""{options.UniqueId}""]');
 
				api.register({{
					 hasValue: function() {{
							 var val = options.filter(':checked').val();
							 if (!val || val.length == 0) {{
									 return false;
							 }} else {{
									 return true;
							 }}
					 }},
					 val: function(val) {{
							 if (val === undefined) {{
									 return options.filter(':checked').val();
							 }} else {{
									 options.prop('checked', false);
									 options.filter('[value=""' + val + '""]').prop('checked', true);
							 }}
					 }}
				}});

				options.on('change', function() {{
						api.changed(options.filter(':checked').val());
				}});
		}});
		</script>
	");
}

This method should render the property with the provided templateName on the provided writer. The options parameter includes details about the property being rendered, its value, the client-side ID of the property being rendered, the JSON API for the registration and client-behavior of the dynamic form, the form's ID into which the property is being rendered, formatting details, and other utility properties and methods.

The method then renders its custom UI and registers it against the dynamic form (so that its value is saved and changes are propagated to the dynamic form for client-side rule execution) through the JSON API.

In the example above, the custom property template named "mypropertytemplate" renders a radio button list of two options and allows the selection of those options. The plugin can then use this template in the definition of a property, for example:

var property = new Property
{
	Id = "message",
	LabelText = "Welcome message",
	DataType = "String",
	Template = "mypropertytemplate"
};

myConfigurationPropertyGroup.Properties.Add(property);

When built and deployed, this plugin would render its "message" property as: