That International Telephone Input Jquery Plugin (the one with flags) as an Umbraco 7 Property Editor

Written by @marcemarc on Wednesday, 19 March 2014

Hey, so have been working on a few different multi-lingual International sites in Umbraco over the last couple of months, and the common theme for these is that International Telephone Number input and validation either inside Umbraco or on front-end forms is a bit complicated. Mainly because different countries have different length telephone numbers, so with regex's you end up saying well smallest number possible is I think 9 digits (Sweden ?), and the longest is 15...

So it's inprecise.

One client was adamant they wanted to force users to provide a valid telephone number, which I did point out was difficult without actually calling the person up and asking them "is this your telephone number ? did you just type it in online ?" (although if pushed I'm sure we could build something with http://www.twilio.com/ to automate this, scary thought)

I was thinking out aloud, if the customer puts 0 in the telephone field, it's not because they don't understand what their telephone number is, or what a valid format for a telephone number is, it's well, because they don't want to give you their telephone number, because you are going to try and ring them and sell them something, and well people don't always like that, especially if they are filling in a form online, and if your business is solely based on these telephone leads, then you might perhaps want to rethink it slightly because in 5yrs, 10yrs... is that sort of business going to exist ?

And then the client goes a bit sulky so I plugin the International Telephone Input Jquery Plugin (https://github.com/Bluefieldscom/intl-tel-input), and everyone is all smiles again - because it's got flags !! and the country codes, and it works with Google's libTelephoneNumber (https://code.google.com/p/libphonenumber/

Some description

and so it's pretty good at indicating what is a valid telephone number in a particular country or not, and the client is pleased because people have to fill in a valid telephone number and I don't point out: 'yes but they can still opt to put someone else's number in', and it's got flags.

Anyway such is the plugin's popularity, clients have begun asking for it within Umbraco for editing phone numbers, it's great for when the editor needs to specify the country code on a number from a country they're not familiar with, and so I've just had to wrap it up quite hastily today as an angular property editor, and I thought I'd put it up on our.umbraco as a package, in case someone else might make it better... or it may do for someone who is in a similar haste.

It's simple, there is one prevalue you can set on the property editor which is a json object as a string, that is any of the options provided for the International Telephone Input plugin (well I say any, I haven't tested them all, but you should be ok to set defaultCountry, preferredCountries and onlyCountries)

Some description

Then when a user fills in the number, there is a visual indication that the number is valid or invalid based on the selected Country flag,

Some description

Some description

it doesn't prevent the user saving an invalid telephone number, it just makes the editor aware that it is.  I think it's possible now or will be soon, to have a property editor take responsibility for it's validation within Umbraco, and so it could be set that a valid telephone number was required, and the page couldn't be published without one, but I didn't need that today, so it doesn't, ok ? but it has got flags.

I also needed to have more than one telephone field on the page, and I realised in the past I've been thinking too Jquery like, falling into the trap of manipulating the Dom from the controller, binding a plugin via a jquery selector of an ID, which is just plain wrong in angular.

(ASIDE, you may have noticed if you ever have a problem working out how to do something in angular it is only a matter of time before someone suggests using a directive, it's a cool thing to say, you know, if you're still at that bluffing stage).

So I've created a directive. A directive and don't quote me on this, is like a thing you can register and use in the html, that when it gets rendered fires some javascript, kind of (see http://docs.angularjs.org/guide/directive). So I've created an intTelNumber directive, and in the html set this on my input element, when this is rendered my directive fires, and my 'link' code has a reference to the element the directive is on, and I use this to bind the plugin to the control, so I don't need to know the id of the element in the html to trigger the plugin.

Directive:

app.directive('intTelNumber', function() {
 return {
// Restrict it to being an attribute
restrict: 'A',
// responsible for registering DOM listeners as well as updating the DOM
link: function (scope, element, attrs) { scope.$watch('loaded', function () {
if (scope.loaded == true) {

// apply plugin
element.intlTelInput(scope.options);
//validate loaded number
var countryCode = element[0].nextSibling.children[0].children[0].className.split(" ")[1];
scope.validateTelephoneNumber(element[0].value, countryCode);

}}); }
}
});

Only problem was this was happening before the International Telephone Input plugin had loaded, so I put a $watch on property in scope called 'loaded' and changed this value to true when the assetservice concludes the libraries are there. it doesn't feel right, maybe I need to use a directive, oh..

The other tricky thing was I couldn't seem to access within the controller the IntTelInput plugin's existing 'isValidNumber' and 'GetCountryCode' properties and methods. Time was running out but I figured the way the plugin works is to store and retrieve the country code from a css class on an unrelated div element, just below the input element, so the hack to access this was:

element[0].nextSibling.children[0].children[0].className.split(" ")[1]

So it seems to work. You can try it out here.