From the Archives : Telephone Input with Flags

This little code example comes from the Consultants Guide to JavaScript Extensions for Oracle Policy Modeling. There are 70 (!) code Zips provided with complete examples in the book. This one is so often requested that as a special Memorial Day article and gift, you can get it for a limited time in the Online Store. The Zip File is available for free.

Let’s look at the requirements – add a phone number flag and dialling code selector to the input field. It uses the international telephone number input code over on github, which itself uses some Google code as a starting point (see GitHub) .

Since this code was written, the component has got even better, and in the latest version of the telephone input with flags, it has new options for autoformat as you type and a bunch of other things that didn’t exist when this demo was originally built. So you can try out the latest version (this demo was written on v15, and the current version is v23).

In the original demo, we just unzipped the release code (a couple of JS files, an image file for the flags, and a stylesheet for the flag component. Then we tweaked the custom Input a little with some CSS to make it look right.

OraclePolicyAutomation.AddExtension({
        customInput: function(control, interview) {
                if (control.getProperty("customName") == "mobilePhoneInput"){
						 var previousMobilePhone = interview.getValue("applicant_mobile");
                        return {
                                mount: function(el) {
									var s = $('<INPUT type="tel" id="mobilePhone" class="opaclone" "style="max-width: 280px; outline: rgb(114, 119, 128) solid 1px; outline-offset: 0px; border: 0px; padding: 0.4em 0.8em; box-sizing: border-box; width: 100%; font-family: inherit; font-size: inherit; font-weight: inherit; font-style: inherit; color: inherit;"/>');
									s.change(function() {
										var mobileNumber = configuredInput.getNumber(intlTelInputUtils.numberFormat.E164);
										interview.setInputValue("applicant_mobile", mobileNumber);
                                        //trigger validation rules when mobile phone cleared
                                        var mobileInput = document.getElementById("mobilePhone").value;
                                        if (mobileInput == '') {
                                         interview.setInputValue("applicant_mobile", '');
                                        }
									});
									s.blur(function () {
										validatemobilePhoneNumber();
									});
									
									s.appendTo(el);
									var input = document.querySelector("#mobilePhone");
									configuredInput = intlTelInput(input, {
											initialCountry: "US",
											preferredCountries: [],
											separateDialCode: true,
											autoPlaceholder: "off",
											formatAsYouType : true,
											formatOnDisplay : true
									});
									
									if(previousMobilePhone != '' && previousMobilePhone != undefined)
									{
										configuredInput.setNumber(previousMobilePhone);
									} 
                                } ,
                                validate: function (el) {
									return validatemobilePhoneNumber();
                                }
                        }
                }
        }
});
function validatemobilePhoneNumber() {
    //If the phone number is a) more than 0 characters and b) an invalid number then we should show an error message
    //Otherwise remove all existing error messages
    $("#phoneError").remove();
    if($("#mobilePhone").val().length > 0)
    {
        var mobileNumber = configuredInput.isValidNumber();
        if(mobileNumber == false)
        {
            var errorMessage = "<br><span id = 'phoneError' style='color:#df0000'>Please enter a valid  phone number</span>";
            $("#mobilePhone").parent().append(errorMessage);
            return false;
        } else
        {
            return true;
        }
    } 
}

The code above does the absolute minimum – builds the input, adds the trigger for the flags and lets the code do the rest. Of course it is purely educational. Some of the validation could and should be removed and achieved in Oracle Policy Modeling rules.

Have fun. You may also be interested in the posts about dynamic masking.

Telephone Input Example

How to use this example?

Firstly, let’s deal with the basics – many of you will know this already but I write it here in case someone new is dropping by.

In my example Zip File (which I recommend you download again, as some images were missing), there are several files

  • The only files that I added are highlighted. The others are provided in version 15 of the the external library. We only need the built files from the provider.

Of the highlighted files, only phoneNumber.js is relevant to this example. The CSS file is a quick file created by me, to ensure that my Input Extension is the same as a standard one in terms of visual look and feel. The 2jquery-3.3.1.min.js is just a copy of jQuery that I needed for my quick demonstration, since you can see in line 58 above for example, that I used jQuery to select the input. I could of course replace that with non-jQuery code.

Back to the example. phoneNumber.js is a typical input extension. We have to respect the following golden rules when creating extensions:

  1. Extensions must only change the cosmetics, not the logic of a determination
  2. Extensions use a specific, defined format created for the Oracle Policy Modeling JavaScript API. We can’t just write JavaScript and expect it to work. We have to build a file according to the rules.

The basic rule is this – a JavaScript extension has a type (in my case customInput) which defines what it does. In this case, it is an input.

Your JavaScript file created is for a single kind of extension (text input, label, search input and so on). Every JavaScript extension has a series of keys (for example: Mount, Unmount, Validate, Update, Search) that correspond to events that occur during the life of the Control. You write code in these. Not all Controls need all keys (a label, since it is read-only, would not need a Validate key). A JavaScript Extension can leverage other files (jQuery, JQuery UI, external libraries etc.) placed in the resources folder or pulled in using Script tags or asynchronous calls.

So in the case above, there is a Mount key. This is the code that executes when the control is loaded on the screen. Used in almost all cases, the mount is called when your extension must be initialised – for example, because you have placed it on a Screen and that Screen is now going to be shown to the user. You should initialise your control, add HTML to the page and basically do everything you need for the control extension to function. For example if it is a label, print the label. If it is an input, draw the input on the Screen.

Validate: Used in Input and Full Input. This is fired when the user moves to another Screen or another Control. The exact timing depends on the Interview parameter called Show Errors (Immediately or On Navigate). Your code must look at the value entered by the user, and compare it to any logic you need to apply. For example, if the user has entered a zip code, do you want to validate it is in Washington State? The exact nature of the validation is up to you, of course. In the example, the input uses the external code to make sure a valid phone number has been entered.

Unmount: The opposite of Mount. It is called when your extension is no longer needed, for
example the Screen is being removed because the user clicked Next. You should tidy up
anything you are doing, remove the HTML from the page, close any connections and basically be a good citizen and clean up. You will notice in my example I don’t have any Unmount code. I’m not a good citizen in this case.

If the downloaded example works for you, and you want to take it a step further, look out for the following points

  1. The external library has changed a lot between v15 an v23 – the external library version has changed. So if you want to work with the new version, download it from GitHub but don’t just add it to the existing project – mixing files from different versions will not work.
  2. Also, ensure you only add the build files to your project – not everything in the Zip is relevant / needed
  3. If you are looking for more information about how Extensions work in Oracle Policy Modeling, invest in training or a book about them such as Consultants Guide to JavaScript Extension for Oracle Policy Modeling.

Now let’s look at creating a new version using the latest code. Here is an example, so you can see the differences.

OraclePolicyAutomation.AddExtension({
	customInput: function (control, interview) {
		if (control.getProperty("customName") == "mobilePhoneInput") {
			return {
				mount: function (el) {
					var stylesheet_tag_addition = document.createElement('link');
					stylesheet_tag_addition.setAttribute('href', 'https://cdn.jsdelivr.net/npm/intl-tel-input@23.0.10/build/css/intlTelInput.css');
					stylesheet_tag_addition.setAttribute('rel', 'stylesheet');
					stylesheet_tag_addition.setAttribute('type', 'text/css');
					document.getElementsByTagName('head')[0].appendChild(stylesheet_tag_addition);
					var s = $('<INPUT type="tel" id="mobilePhone" class="opaclone" "style="max-width: 280px; outline: rgb(114, 119, 128) solid 1px; outline-offset: 0px; border: 0px; padding: 0.4em 0.8em; box-sizing: border-box; width: 100%; font-family: inherit; font-size: inherit; font-weight: inherit; font-style: inherit; color: inherit;"/>');
					$.ajax({
						url: 'https://cdn.jsdelivr.net/npm/intl-tel-input@23.0.10/build/js/intlTelInputWithUtils.min.js',
						dataType: "script",
						success: initCode
					});
					function initCode() {
						var input = document.querySelector("#mobilePhone");
						var iti = window.intlTelInput(input, {
								utilsScript: "https://cdn.jsdelivr.net/npm/intl-tel-input@23.0.10/build/js/utils.js",
							});
						var previousMobilePhone = interview.getValue("applicant_mobile");
						if (previousMobilePhone != '' && previousMobilePhone != undefined) {
							iti.setNumber(previousMobilePhone);
						}
					}
					s.change(function () {
						var input = document.querySelector('#mobilePhone');
						var iti = intlTelInput.getInstance(input);
						var mobileNumber = iti.getNumber();
						interview.setInputValue("applicant_mobile", mobileNumber);
						//trigger validation rules when mobile phone cleared
						var mobileInput = document.getElementById("mobilePhone").value;
						if (mobileInput == '') {
							interview.setInputValue("applicant_mobile", '');
						}
					});
					s.appendTo(el);
				},
				validate: function (el) {
					return validatemobilePhoneNumber();
				}
			}
		}
	}
});
function validatemobilePhoneNumber() {
	//If the phone number is a) more than 0 characters and b) an invalid number then we should show an error message
	//Otherwise remove all existing error messages
	$("#phoneError").remove();
	if ($("#mobilePhone").val().length > 0) {
		var input = document.querySelector('#mobilePhone');
		var iti = intlTelInput.getInstance(input);
		var mobileNumber = iti.isValidNumber();
		if (mobileNumber == false) {
			var errorMessage = " <span id = 'phoneError' style='color:#df0000'>Please enter a valid  phone number</span>";
			$("#mobilePhone").parent().append(errorMessage);
			return false;
		} else {
			return true;
		}
	}
}


Firstly the obvious one – this is code written in a hurry with lots of unnecessary stuff in it, to help someone out :). Next, we load from a CDN. So we remove all the external files from our resources directory. All that remain are our files.

Thus, we use a dynamic link to pick up the CSS and Ajax (as a quick and dirty demo) to load the script. We load the script that includes the utilities. So we only need to load that once.

Then we initialise the HTML with few changes. We set the control to any existing value that OPM has available, and if you change the number we validate it.

Here is it in the flesh:

video
play-sharp-fill

The Zip File example is in the Store, now with both examples attached.

Author: Richard Napier

After 8 years in case management and ERP software roles, Richard Napier joined Siebel Systems in 1999 and took up the role of managing the nascent Siebel University in Southern Europe. He subsequently was Director of Business Development and Education for InFact Group (now part of Business & Decisions) for 8 years. He now runs Intelligent Advisor IT Consulting OÜ. Owner of intelligent-advisor.com, he also is Co-Founder of the Siebel Hub.

One thought on “From the Archives : Telephone Input with Flags

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Intelligent Advisor IT Consulting Serving Customers Worldwide
Hide picture