LOADING...

Preview

Pen ID
Unlock Campus Themeforest adv

 

Code

Angular Demo Application

SA Identity Number

This Codepen was developed by: Ian Joubert

A Codepen to demonstrate Angular Material design elements / theme providers, custom form element validators and parsers, Angular message directive, ControllerAs syntax, as well as custom directives with isolate scope. Feel free to fork this.

You entered an invalid birthdate
This is not a valid South African identity number
The number entered is too long
Valid identity number format is 999999 9999 999
Form Input Errors

{{myForm.saIdentity.$error}}

ngModel Value (Parsed)

{{myCtrl.saIdentity}}

South African Identity (Extracted)

Valid:{{myCtrl.verifiedSaIdentity.Valid}}

Birthdate:{{myCtrl.verifiedSaIdentity.BirthDate}}

Gender:{{myCtrl.verifiedSaIdentity.Gender}}

Citizenship:{{myCtrl.verifiedSaIdentity.Citizenship}}

CSS
body {
  background: rgba(0, 0, 0, 0.1);
  font-size: 1.2em;
}

md-card {
  background: #fff;
}

article h1 {
  color: #673AB7;
  margin: 8px 0 4px;
}
article h3 {
  color: rgba(0, 0, 0, 0.4);
  margin: 8px 0 4px;
}
article small {
  color: rgba(0, 0, 0, 0.2);
}
article p {
  color: rgba(0, 0, 0, 0.4);
  text-align: center;
  line-height: 1.2em;
}

.result, errors {
  color: rgba(0, 0, 0, 0.4);
}
.result h3, errors h3 {
  margin: 4px 0;
  padding-left: 24px;
}
.result div[layout], errors div[layout] {
  margin-bottom: 24px;
}

.message {
  color: rgba(0, 0, 0, 0.2);
  margin-left: 4px;
}
JS
angular.module('myApp', ['ngMaterial', 'ngMessages'])

    .controller('myController',function(){
  				var self = this;
  				self.saIdentity = {};
  				self.verifiedSaIdentity = {};
		} )
    .config( function($mdThemingProvider) {

        $mdThemingProvider.theme('default')
            .primaryPalette('deep-purple')
            .accentPalette('yellow');
    })

	.factory('moment', ['$window',
		function($window) {
			return $window.moment;
		}
	])


	.directive('validatorIdNumber',[

		'moment',

		function(moment){

			var link = function(scope, element, attrs, ngModelCtrl){

			// --------------------------------------------------------------------------------
			// Attributes
			// --------------------------------------------------------------------------------

					var self = element;
					var ID_REGEXP = /^[\d\s]+$/;
					var CCASE_REGEX = /([a-z](?=[A-Z]))/g;
					

			// --------------------------------------------------------------------------------
			// Constructor
			// --------------------------------------------------------------------------------

					var SouthAfricanID = function() {

						var SaId = this;
            var identity = {};

						SaId.getIdentity = function(){
							return identity;
						};

						SaId.checkIDNumber = function(idNumber) {
							var value = String( idNumber ).replace(/[^0-9]+/g,'');
							var number = value.substring(0, value.length - 1);
							var isValid = ( generateLuhnDigit(number) === +value[value.length - 1] );

							SaId.Value = value;
							SaId.Valid = isValid;
							SaId.extractIdData(value);
              
              identity = SaId;

							return identity;
						};

						SaId.getBirthDate = function(idNumber) {
							var value = String( idNumber ).replace(/[^0-9]+/g,'') || SaId.Value ;
							return ( SaId.BirthDate = moment( value.substr(0,6), 'YYMMDD' ).format('YYYY-MM-DD') );
						};

						SaId.getGender = function(idNumber) {
							var value = String( idNumber ).replace(/[^0-9]+/g,'') || SaId.Value ;
							return ( SaId.Gender = +value.substring(6, 7) < 5 ? 'female' : 'male' );
						};

						SaId.getCitizenship = function(idNumber) {
							var value = String( idNumber ).replace(/[^0-9]+/g,'') || SaId.Value ;
							return ( SaId.Citizenship = +value.substring(10, 11) === 0 ? 'South Africa' : 'foreigner' );
						};

						SaId.extractIdData = function(idNumber) {
							var value = String( idNumber ).replace(/[^0-9]+/g,'') || SaId.Value ;
							SaId.getBirthDate(value);
							SaId.getGender(value);
							SaId.getCitizenship(value);
						};

						return SaId;
					};

			// --------------------------------------------------------------------------------
			// Functions
			// --------------------------------------------------------------------------------

					self.Initialize = function() {

						var EFFECTORS = [validLength, validBirthDate, validSaIdentity, parseNumber, formatNumber];
						addEffectors(EFFECTORS);

						element.on('keyup', onKeyUpEvent);
						element.on('blur', onBlurEvent);
            
            scope.saIdentity = new SouthAfricanID();
					};

					// ADDING Validators, Formatters & Parsers (based on first word of camelcase function names)
					function addEffectors (array){
						angular.forEach(array, 
							function(item){
								var nameSegments = (item.name.replace( CCASE_REGEX, '$1 ')).split(' ');

								switch(nameSegments[0]){
									case 'valid': ngModelCtrl.$validators[item.name] = item; break;
									case 'parse': ngModelCtrl.$parsers.push(item); break;
									case 'format': ngModelCtrl.$formatters.push(item); break;
								}
							}
						);
					}				

					// VALIDATOR FUNCTIONS
					// To add new validators just add the validator function to the array of validators
					
					function validBirthDate(modelValue, viewValue){
						var value = String( viewValue || modelValue ).replace(/[^0-9]+/g,'');

						if(!!value && value !== ''){
							return moment(value.substr(0,6),'YYMMDD').isValid();
						}
						return true;
					}

					function validSaIdentity(modelValue, viewValue){
						var value = String( viewValue || modelValue ).replace(/[^0-9]+/g,'');

						if(value && value !== '' && value.length === 13){
              return  scope.saIdentity.checkIDNumber(value).Valid;
						}
						return true;
					}

					function validLength(modelValue, viewValue){
						var value = String( viewValue || modelValue ).replace(/[^0-9]+/g,'');

						if(value && value !== ''){
							return ((value.length > 13) ? false : true);
						}
						return true;
					}


					// PARSER FUNCTIONS
					// To add new parsers just add the parser function to the array of parsers

					function parseNumber(viewValue) {

						if (viewValue === null || viewValue === undefined) { return undefined; }
						if (!!viewValue && ID_REGEXP.test(viewValue)) { 
							return viewValue.replace(/[^0-9]+/g,'');
						}
						return viewValue;
					}


					// FORMATTER FUNCTIONS
					// To add new formatters just add the formatter function to the array of formatters

					function formatNumber(modelValue){
						var valueString = String(modelValue).replace(/[^0-9]+/g,'');
						var date = valueString.substr(0,6);
						var gender = valueString.substr(6,4);
						var other = valueString.substr(10,3);
						
						valueString = ((date.length >= 6) ? date + ' ': date) + ((gender.length >= 4) ? gender + ' ': gender) + other; 
						return valueString;
					}


					// EVENT LISTENERS
					
					function onKeyUpEvent(event){
						var keyCode = event.keyCode;
						var ignoredKeys = [8,46,13,37,39,38,40];
						var value = String(event.srcElement.value);

						if(ignoredKeys.indexOf(keyCode) === -1){

							ngModelCtrl.$setViewValue(formatNumber(value));
							ngModelCtrl.$render();
							scope.$apply();
						}
					}

					function onBlurEvent(event){
						var value = String(event.srcElement.value);

						ngModelCtrl.$setViewValue(formatNumber(value));
						ngModelCtrl.$render();
						scope.$apply();
					}


					// Test CHECKSUM (last) number of South African Identity numbers
					function generateLuhnDigit (value) {	

						var count = 0;
						var total = 0;

						for (var i = 0; i < value.length; i++) {

							var multiple = count % 2 + 1;
							var temp = multiple * +value[i];

							temp = Math.floor(temp / 10) + (temp % 10);
							total = total + temp;
							count++;
						}

						total = (total * 9) % 10;
						return total;
					}




				//Initialise directive
				self.Initialize();

			};  //End of LINK function

		// --------------------------------------------------------------------------------
		// Configuration
		// --------------------------------------------------------------------------------

		return ({
			require : 'ngModel',
			scope: {
        saIdentity:'='
      },
      controller: 'myController',
			restrict: 'A',
			replace: false,
			link: link,
		});


	}
  ]);

Description

Sample code to illustrate custom Angular formatters, validators and isolate scoped directive. The Pen validate and format an Angular Material Design South African identity input to a specific regex pattern and the LuhnDigit validation process.
Wed, 12/27/2017 - 06:58

Related Codes

Pen ID
Pen ID
Pen ID
Square Adv