src/validation/validation.js
/**
* @ngdoc directive
* @name patternfly.validation:pfValidation
* @restrict E
* @element INPUT
* @scope
*
* @description
* Directive used for input validation based on custom function.
*
* @param {expression=} pfValidationDisabled If true, the validation is disabled, it is enabled otherwise.
*
* @example
<example module="patternfly.validation">
<file name="index.html">
<div ng-controller="ValidationDemoCtrl">
<form class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label" for="message">Initially valid:</label>
<div class="col-sm-10">
<input class="form-control" type="text" ng-model="myValueValid" pf-validation="isNumber(input)"/>
<span class="help-block">The value you typed is not a number.</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="message">Fixed Number:</label>
<div class="col-sm-10">
<input class="form-control" type="text" ng-model="myValue" pf-validation="isNumber(input)"/>
<span class="help-block">The value you typed is not a number.</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="message">Number:</label>
<div class="col-sm-10">
<input class="form-control" type="text" ng-model="myValue" pf-validation="isNumber(input)" pf-validation-disabled="isValidationDisabled"/>
<span class="help-block">The value you typed is not a number.</span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="message">Validation disabled:</label>
<div class="col-sm-10">
<input class="form-control" type="checkbox" ng-model="isValidationDisabled"/>
</div>
</div>
</form>
</div>
</file>
<file name="script.js">
angular.module( 'patternfly.validation' ).controller( 'ValidationDemoCtrl', function( $scope ) {
$scope.myValue = "Change this value to be a number";
$scope.myValueValid = 42;
$scope.isValidationDisabled = false;
$scope.isNumber = function (value) {
if (isNaN(value)) {
return false;
}
return true;
}
});
</file>
</example>
*/
angular.module('patternfly.validation', []).directive('pfValidation', function ($timeout) {
'use strict';
return {
restrict: 'A',
require: 'ngModel',
scope: {
pfValidation: '&',
pfValidationDisabled: '='
},
link: function (scope, element, attrs, ctrl) {
scope.inputCtrl = ctrl;
scope.valEnabled = !attrs.pfValidationDisabled;
scope.$watch('pfValidationDisabled', function (newVal) {
scope.valEnabled = !newVal;
if (newVal) {
scope.inputCtrl.$setValidity('pfValidation', true);
toggleErrorClass(false);
} else {
validate();
}
});
// If validation function is set
if (attrs.pfValidation) {
// using $timeout(0) to get the actual $modelValue
$timeout(function () {
validate();
}, 0);
} else if (!scope.inputCtrl.$valid && scope.inputCtrl.$dirty) {
toggleErrorClass(true);
}
scope.$watch('inputCtrl.$valid', function (isValid) {
if (isValid) {
toggleErrorClass(false);
} else {
toggleErrorClass(true);
}
});
scope.$watch('inputCtrl.$modelValue', function () {
validate();
});
function validate () {
var valid;
var val = scope.inputCtrl.$modelValue;
var valFunc = scope.pfValidation({'input': val});
if (!attrs.pfValidation) {
valFunc = true;
}
valid = !val || valFunc || val === '';
if (scope.valEnabled && !valid) {
toggleErrorClass(true);
} else {
toggleErrorClass(false);
}
}
function toggleErrorClass (add) {
var messageElement = element.next();
var parentElement = element.parent();
var hasErrorM = parentElement.hasClass('has-error');
var wasHidden = messageElement.hasClass('ng-hide');
scope.inputCtrl.$setValidity('pf-validation', !add);
if (add) {
if (!hasErrorM) {
parentElement.addClass('has-error');
}
if (wasHidden) {
messageElement.removeClass('ng-hide');
}
}
if (!add) {
if (hasErrorM) {
parentElement.removeClass('has-error');
}
if (!wasHidden) {
messageElement.addClass('ng-hide');
}
}
}
}
};
});