Tag: Input Extension

Dynamic Input Mask JavaScript Extension

Dynamic Input Mask JavaScript Extension

This week I was lucky enough to be chatting to a reader when he shared a requirement for a dynamic mask. The exact concept was simple : when entering a telephone number, if the end user of the Interview types a number first, then the mask should default to the national format – for example (555) 1234-1234 – but if the end user types the international “+” prefix first then the mask should switch to a different one, for example +00 000 0000 0000 or whatever is appropriate. Outside of this example, there are frequently situations where more than one mask is needed, depending on some criteria or some fragment of data entry.

We should not forget of course that if all we want is a simple mask, then Intelligent Advisor has got it covered with the standard out of the box functionality. To implement a simple, static mask simply requires us to create an attribute of type Text and to select Masked Input from the Interview Ribbon before specifying the mask in the Input Mask dialog.

As an example, the following shows a Masked Input Control with a specific mask being implemented. In addition, you can see the Hint Text in the Interview tab shows the result in case you forget.

Clearly this is going to produce a good mask. But it cannot be changed dynamically, as it is part of the Control properties at runtime. So the possible solution is to use an Extension. In this case, a customInput. For the purposes of demonstration, we chose to use the jQuery Mask plugin. You can find more about it at the address : https://igorescobar.github.io/jQuery-Mask-Plugin/docs.html. The most interesting element is the fact that it supports dynamic masks. It uses the keypress event to enable the developer to check the character(s) and then change the mask. So this sounded like a great idea, and indeed proved quite straightforward. The code below shows that in fact there are several steps needed : define the two masks, and also handle the case when the area is blanked by the user.

Happily we found an old project where we had already used this dynamic input mask technique and adapted it for today.

Dynamic Mask

Here is the example code, of course you can get the Zip file from the Shop. There are some comments below.

/*  Generated by the OPA Hub Website Code Generator 30/11/2018 22:41
Educational Example of Custom Input Mask Extension for Oracle Policy Automation
I will remember this is for demonstration purposes only.
 */
OraclePolicyAutomation.AddExtension({
	customInput: function (control, interview) {
		if (control.getProperty("name") == "xMask") {
			return {
				mount: function (el) {
					console.log("Starting name:xMask customInput Mount");
					var div = document.createElement("input");
					div.id = "xMask";
					div.value = control.getValue();
					el.appendChild(div);
					var oldVal;
					$('#xMask').on('keypress', function () {
						var val = this.value;
						if ((val != oldVal) && (val.length == 1)) {
							oldVal = val;
							if (oldVal == '+') {
								$('#xMask').mask('+999-9999-9999');
								$('#xMask').val(oldVal)
							} else {
								$('#xMask').mask('(999)-999-99999');
								$('#xMask').val(oldVal)
							}
						} else if (val.length == 0) {
							$('#xMask').unmask();
						}
					});
					console.log("Ending name:xMask customInput Mount");
				},
				unmount: function (el) {
					if (control.getProperty("name") == "xMask") {
						console.log("Starting name:xMask customInput UnMount");
						var xMask = document.getElementById("xMask");
						xMask.parentNode.removeChild(xMask);
						console.log("Ending name:xMask customInput UnMount");
					}
				}
			}
		}
	}
})

As you can see in this dynamic input mask demo, there is only really the mount to worry about. We use the keypress event and switch the mask based on the previous character pressed on the keyboard. And if no characters exist in the control we remove the mask ready for the next try. Here is a short video demonstrating the effect, and comparing to a static mask. The input control extension has not had any CSS formatting applied so it appears a little smaller than the standard. This can easily be changed.

video

Have a nice day! (the documentation about standard input mask functionality can be found online here).

Input Validation in an Input Extension – IBAN Validation

Input Validation in an Input Extension – IBAN Validation

A funny thing happened today – I came across a forum post that was talking about exactly what we had been describing to someone else the same day. Odd. These confinement measures play tricks with your mind. Anyway here is the scenario, it’s about input validation.

The customer needs to validate a banking account number in IBAN format in Oracle Policy Automation as part of an HTML Interview. What are the options for input validation?

There are several ways to handle this

  1. If you are just validating one country-origin IBAN numbers then you could certainly use Regular Expressions on your Input Text Attribute. A checksum rule would provide extra validation.
  2. Write a lot of Error or Warning Rules to achieve the same.
  3. But given there are many formats and many countries, if you need something bigger then you had better use some help!

There are standalone JavaScript libraries like this one, or you might use the jQuery Validator instead. It comes with IBAN validation as part of the additional methods supplied with it.  Since a lot of people are familiar with jQuery, and since Oracle Policy Modeling already uses it, we decided to opt for that solution for input validation.

We downloaded the validator and the additional files. we ensured that jQuery was accessible to the Project (in short, we clicked the Styles button in the Interview, then the Custom.. button and said OK before pasting the files in the folder). If this was a real-life case we would load the files in the correct order programmatically (jQuery, Validator, then additional stuff) but for this quick hack we renamed the files in alphabetical order to make sure they loaded like A, B and C.

We created an Input attribute, and named it something like this:

Input Validation - Create Attribute

Then we added it to the Screen and hooked up a custom property to make sure the code is executed for the IBAN element.

Input Validation Setup Screen

Then I fired up my trusty Code Generator and created a template Input Extension. I edited the Validate handler and this is the complete input extension. Of course this is the bare bones but it will do for a start :

//*  Generated by the OPA Hub Website 18/03/2020 08:06
Educational Example of Custom Input Extension for Oracle Policy Automation
I will remember this is for demonstration purposes only.
 */
OraclePolicyAutomation.AddExtension({
	customInput: function (control, interview) {
		if (control.getProperty("name") == "xIBAN") {
			return {
				mount: function (el) {
					console.log("Starting name:xIBAN customInput Mount");
					var div = document.createElement("input");
					div.id = "xIBAN";
					div.value = control.getValue();
					div.setAttribute("data-rule-iban", "true");
					el.appendChild(div);
					console.log("Ending name:xIBAN customInput Mount");
				},
				update: function (el) {
					console.log("Starting name:xIBAN customInput Update");
					console.log("Ending name:xIBANcustomInput Update");
				},
				validate: function (el) {
					console.log("Starting name:xIBAN customInput Validate");
					//errorplacement ensures the standard message is not visible
					var validator = $(".opa-interview").validate({
							errorPlacement: function (error, element) {
								return true;
							}
						});
					var returnvalue = validator.element("#xIBAN")
					if (returnvalue === true) {
						control.setValue(document.getElementById("xIBAN").value);
						return true;
					} else {
						return 'Your Message Here - THIS IS NOT A VALID IBAN'
					}
					console.log("Ending name:xIBAN customInput Validate");
				},
				unmount: function (el) {
					if (control.getProperty("name") == "xIBAN") {
						console.log("Starting name:xIBAN customInput UnMount");
						var xIBAN = document.getElementById("xIBAN");
						xIBAN.parentNode.removeChild(xIBAN);
						console.log("Ending name:xIBAN customInput UnMount");
					}
				}
			}
		}
	}
})

Input Validation

Input Extension – Summary

The basic idea is simple – when the Validate handler fires, pull the form and the input element and validate it as an IBAN number. If it passes, then there is no error message. Otherwise the validate fails and you can tell the user. You can have a more interesting message than this of course.

The Zip Archive is in the OPA Hub Shop. Have fun!

Input Extensions – Input Validation

Input Extensions – Input Validation

Following on from the recent posts about Errors and Input Extensions, this week we’re going to look at input validation and error handling. Not, you will understand, error handling in the JavaScript sense (writing try…catch and so forth) but how to handle errors that the user makes when entering data in your Input Extension.

Let’s set the scene with some simple examples. You have created an Input Extension in the form of an INPUT tag that displays an attribute for the user to enter. You intend to use the validate handler to do the work of testing the user’s data entry and flagging it to the user if they have made a mistake.

So you begin by understanding that the validation handler is ultimately a three way trigger : you can return true (in which case there is no error, and the data entered passes validation) or false (you wish to signal to the user there is an error, without an error message) or better still  a text string which means yes there is an error, and furthermore here is a text string to tell you what it is. For our little example, we will therefore be looking to handle true  and text string.

Basic Validation

var currentValue = document.getElementById("xInput").value;
var bBanana = document.getElementById("xInput").value === 'BANANA';

In the above example, we retrieve the current value of the INPUT and compare it to the text string “BANANA”. If you have entered “BANANA” then you have passed our validation (true) and if not (false).

if(!bBanana) 
{
return "JavaScript Validation Error";
}

Great. The case is solved, to paraphrase a famous detective. But then, one day, your Input Extension stops working. It mysteriously refuses to validate your user’s data entry, even when the data entry is correct. It simply refuses to let the user go forward, but there is no error message. So where is the problem coming from?

You take a look at the attribute you are supposed to be validating and notice that the rule designer has added something since you last looked:

Input Validation 1

So the rule designer has added a Regular Expression to the attribute. And what you are entering, perhaps, is not matching the RegEx. But how on earth are you supposed to check for that / handle that in an Input Extension? There is no documented process / property set for this, but if you dig down deep enough, you can find the following properties:

Input Validation – RegEx

control._source.config.inputRestriction.regularExpression (the RegEx)

control._source.config.inputRestriction.rawErrorMessage (the message)

The above properties give you access to the rule designer’s RegEx and associated error message. They do NOT, however, test the value of your input against the RegEx. So don’t forget to actually include the RegEx in your validate handler. At a simple level it might be something like this:

var regExpression = new RegExp(control._source.config.inputRestriction.regularExpression); 
var bTestInput = regExpression.test(currentValue);

Again, we will have a boolean variable which will tell us if the text entered has passed the RegEx validation or not. So now you can include this in your standard validation, to be able to present the user with reasonably decent message:

Input Validation - 3

OPA Hub Website Supporters can download an example project from the OPA Hub Shop. You’ll find the official reference online.

Input Extensions – DropDowns

Input Extensions – DropDowns

Many thanks to long-time reader and Oracle Policy Automation expert Aaron H for an interesting discussion just before the holiday season. The subject for this post is as you can tell, Input extensions that are dropdowns.

Our conversation was wide ranging but this article will focus on a couple of things

  1. How to ensure that the extension displays and handles the text and value elements of your list of values
  2. How to handle <uncertain>
  3. How to have a different label for <uncertain>

Along the way this will give us the opportunity to understand the usefulness of the Value() function in a rule. In later posts in this series we will look at other forms of Input, also beyond the basic INPUT or SELECT tag.

So let’s begin with a simple setup – the Zip Archive is available in the OPA Hub Shop by the way) – starting with just one attribute and a Value List:

The initial Value List looks like this – notice that in this case, there is no distinction between the displayed text and the actual value:

Input Extensions - DropDowns

In this simple scenario, one often sees extension code that focuses on the control.getOptions() method and then iterating through the various options from the returned object, something a little like this (for educational purposes only) :

var myChoices = control.getOptions();
for (key in myChoices) {
if(myChoices[key].value)
{
$('#xDropDown').append('<option value="' + myChoices[key]..text.toString() + '">' + myChoices[key].text.toString() + '</option>');
}
}

The code works fine, but makes a few assumptions that can come back and bite later when the rule designer has made changes.

  1. It does not take into account the possible change in the Value List to include display and values.
  2. It will error out if the dropdown becomes non-mandatory since “uncertain” will cause .toString() to fail

So when the developer of the rule changes the Value List to something like this:

Input Extensions - DropDowns 2

The code would no longer be useful since the [key].text and [key].value are two different values. And if we are updating the underlying control, we need to remember that we call control.setValue() so it is expecting a value, not the display value.

So maybe the code gets changed to :

 $('#xDropDown').append('<option value="' + myChoices[key].value + '">' + myChoices[key].text.toString() + '</option>');

Or something similar. All is well and the dropdown is correctly handling things :

Until the attribute is defined as non-mandatory in the Screen where it is displayed. At which point the code breaks again, as the uncertain value is not handled. Let’s take a step back and remind ourselves of the defaut behaviour in these situations, without an extension:

The standard control renders an empty option for the uncertain value. I’ve always considered it a bit of a bug that it does not respect the optional Display Value (in my case, “Not Sure” – see the screenshot a little further up) but always renders a blank, at least in all my browsers.

So in the case of an Input Extension that needs to render the uncertain value (because the control is not mandatory) and also wants to show the Display Value, the code will probably need to have another quick change:

Input Extensions DropDown Code Last One

Which will ensure that the dropdown is rendered with the correct text and value, if there is one. Also, the added bonus is that the display text of uncertain is rendered as we would expect:

Input Extension Showing Uncertain Vlaue

And finally, we have good use of the Value() function so that we can be sure that the correct value is stored in our Interview:

The function above, in a Word document for example, will return the value rather than the display value. So you can drop it onto the final Screen of your testing Project and compare the two to make sure you have gathered the correct one.

Hopefully that was fun and interesting, and you can practice yourself with your own project. As mentioned above the code is available in the OPA Hub Shop. The documentation is of course on the Oracle Intelligent Advisor website.

Worldwide
Logo by Southpaw Projects LLC