From 1b9d52713c32d1b73c90174258ea9b0cc781489a Mon Sep 17 00:00:00 2001 From: Tomasz Bak Date: Sat, 7 Feb 2015 18:37:16 +0100 Subject: [PATCH 1/4] toggle has-error on parent form-group with $validationProvider valid/invalid callbacks --- README.md | 12 ++++++++++++ src/directive.js | 2 ++ src/provider.js | 2 ++ 3 files changed, 16 insertions(+) diff --git a/README.md b/README.md index 86c5648..bf17518 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,18 @@ $validationProvider.setErrorHTML(function (msg) { You can add the bootstrap class `.has-success` in a similar fashion. +To toggle `.has-error` class on bootstrap `.form-group` wrapper for labels and controls, add: + +```javascript +angular.extend($validationProvider, { + validCallback: function (element){ + $(element).parents('.form-group:first').removeClass('has-error'); + }, + invalidCallback: function (element) { + $(element).parents('.form-group:first').addClass('has-error'); + } +}); +``` CHANGELOG ===== diff --git a/src/directive.js b/src/directive.js index 71b7b22..d9c583c 100644 --- a/src/directive.js +++ b/src/directive.js @@ -33,6 +33,7 @@ } ctrl.$setValidity(ctrl.$name, true); if (scope.validCallback) scope.validCallback(); + if ($validationProvider.validCallback) $validationProvider.validCallback(element); return true; }; @@ -64,6 +65,7 @@ } ctrl.$setValidity(ctrl.$name, false); if (scope.inValidCallback) scope.inValidCallback(); + if ($validationProvider.invalidCallback) $validationProvider.invalidCallback(element); return false; }; diff --git a/src/provider.js b/src/provider.js index 9cbf777..c900575 100644 --- a/src/provider.js +++ b/src/provider.js @@ -265,6 +265,8 @@ showErrorMessage: this.showErrorMessage, checkValid: this.checkValid, validate: this.validate, + validCallback: this.validCallback, + invalidCallback: this.invalidCallback, reset: this.reset }; } From c64046a5f1ae8ca3244252a95c0cabdcfb4452ad Mon Sep 17 00:00:00 2001 From: Tomasz Bak Date: Sun, 8 Mar 2015 21:00:24 +0100 Subject: [PATCH 2/4] fix README after merge --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bf17518..daa9709 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,10 @@ angular-validation 1.3.0 Client-side Validation should be simple and clean.
Don't let Client-side Validation dirty your controller. -
Setup your Validation on config phase by using some rules [(example)](https://github.com/huei90/angular-validation/blob/master/dist/angular-validation-rule.js) + +Setup your Validation on config phase by using some rules [(example)](https://github.com/huei90/angular-validation/blob/master/dist/angular-validation-rule.js) +
If you prefer schema over html attributes , try [angular-validation-schema +](https://github.com/thetutlage/angular-validation-schema) [(Demo)](http://plnkr.co/edit/X56HEsDYgYoY8gbSj7cu?p=preview)
And add Validation in your view only. angularjs 1.2.x support to version [angular-validation 1.2.x](https://github.com/huei90/angular-validation/tree/v1.2.x)
From 3b8ee62fa6731115ea135915b7ca813c840dc03e Mon Sep 17 00:00:00 2001 From: Tomasz Bak Date: Sun, 8 Mar 2015 21:08:06 +0100 Subject: [PATCH 3/4] global validCallback should be initial to null also giving some parameter --- src/provider.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/provider.js b/src/provider.js index c900575..121dbd7 100644 --- a/src/provider.js +++ b/src/provider.js @@ -218,6 +218,17 @@ return deferred.promise; }; + /** + * Do this function if validation valid + * @param element + */ + this.validCallback = null; + + /** + * Do this function if validation invalid + * @param element + */ + this.invalidCallback = null; /** * reset the specific form From bd8e73f887722f64b5a3f625ae6bf21d1498e5cf Mon Sep 17 00:00:00 2001 From: Tomasz Bak Date: Sun, 8 Mar 2015 21:08:26 +0100 Subject: [PATCH 4/4] grunt build --- dist/angular-validation.js | 15 +++++++++++++++ dist/angular-validation.min.js | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/dist/angular-validation.js b/dist/angular-validation.js index 324e42d..b2ef4c6 100644 --- a/dist/angular-validation.js +++ b/dist/angular-validation.js @@ -222,6 +222,17 @@ return deferred.promise; }; + /** + * Do this function if validation valid + * @param element + */ + this.validCallback = null; + + /** + * Do this function if validation invalid + * @param element + */ + this.invalidCallback = null; /** * reset the specific form @@ -269,6 +280,8 @@ showErrorMessage: this.showErrorMessage, checkValid: this.checkValid, validate: this.validate, + validCallback: this.validCallback, + invalidCallback: this.invalidCallback, reset: this.reset }; } @@ -312,6 +325,7 @@ } ctrl.$setValidity(ctrl.$name, true); if (scope.validCallback) scope.validCallback(); + if ($validationProvider.validCallback) $validationProvider.validCallback(element); return true; }; @@ -343,6 +357,7 @@ } ctrl.$setValidity(ctrl.$name, false); if (scope.inValidCallback) scope.inValidCallback(); + if ($validationProvider.invalidCallback) $validationProvider.invalidCallback(element); return false; }; diff --git a/dist/angular-validation.min.js b/dist/angular-validation.min.js index 54afe86..1eb44f4 100644 --- a/dist/angular-validation.min.js +++ b/dist/angular-validation.min.js @@ -1 +1 @@ -(function(){angular.module("validation",["validation.provider","validation.directive"])}).call(this),function(){angular.module("validation.provider",[]).provider("$validation",function(){var a,b,c,d,e,f=this,g=function(f){a=f,b=a.get("$rootScope"),c=a.get("$http"),d=a.get("$q"),e=a.get("$timeout")},h={},i={};this.setExpression=function(a){return angular.extend(h,a),f},this.getExpression=function(a){return h[a]},this.setDefaultMsg=function(a){return angular.extend(i,a),f},this.getDefaultMsg=function(a){return i[a]},this.setErrorHTML=function(a){return a.constructor===Function?(f.getErrorHTML=a,f):void 0},this.getErrorHTML=function(a){return'

'+a+"

"},this.setSuccessHTML=function(a){return a.constructor===Function?(f.getSuccessHTML=a,f):void 0},this.getSuccessHTML=function(a){return'

'+a+"

"},this.showSuccessMessage=!0,this.showErrorMessage=!0,this.checkValid=function(a){return void 0===a.$valid?!1:a&&a.$valid===!0},this.validate=function(a){var c=d.defer(),g=0;if(void 0===a)return console.error("This is not a regular Form name scope"),c.reject("This is not a regular Form name scope"),c.promise;if(a.validationId)b.$broadcast(a.$name+"submit-"+a.validationId,g++);else if(a.constructor===Array)for(var h in a)b.$broadcast(a[h].$name+"submit-"+a[h].validationId,g++);else for(var i in a)"$"!==i[0]&&a[i].hasOwnProperty("$dirty")&&b.$broadcast(i+"submit-"+a[i].validationId,g++);return c.promise.success=function(a){return c.promise.then(function(b){a(b)}),c.promise},c.promise.error=function(a){return c.promise.then(null,function(b){a(b)}),c.promise},e(function(){f.checkValid(a)?c.resolve("success"):c.reject("error")}),c.promise},this.reset=function(a){if(void 0===a)return void console.error("This is not a regular Form name scope");if(a.validationId)b.$broadcast(a.$name+"reset-"+a.validationId);else if(a.constructor===Array)for(var c in a)b.$broadcast(a[c].$name+"reset-"+a[c].validationId);else for(var d in a)"$"!==d[0]&&a[d].hasOwnProperty("$dirty")&&b.$broadcast(d+"reset-"+a[d].validationId)},this.$get=["$injector",function(a){return g(a),{setErrorHTML:this.setErrorHTML,getErrorHTML:this.getErrorHTML,setSuccessHTML:this.setSuccessHTML,getSuccessHTML:this.getSuccessHTML,setExpression:this.setExpression,getExpression:this.getExpression,setDefaultMsg:this.setDefaultMsg,getDefaultMsg:this.getDefaultMsg,showSuccessMessage:this.showSuccessMessage,showErrorMessage:this.showErrorMessage,checkValid:this.checkValid,validate:this.validate,reset:this.reset}}]})}.call(this),function(){angular.module("validation.directive",["validation.provider"]).directive("validator",["$injector",function(a){var b=a.get("$validation"),c=a.get("$q"),d=a.get("$timeout"),e=function(a,c,d,e,f){var g,h=c||b.getDefaultMsg(d).success;return g=e.messageId?angular.element(document.querySelector("#"+e.messageId)):a.next(),b.showSuccessMessage&&h?(g.html(b.getSuccessHTML(h)),g.css("display","")):g.css("display","none"),f.$setValidity(f.$name,!0),e.validCallback&&e.validCallback(),!0},f=function(a,c,d,e,f){var g,h=c||b.getDefaultMsg(d).error;return g=e.messageId?angular.element(document.querySelector("#"+e.messageId)):a.next(),b.showErrorMessage&&h?(g.html(b.getErrorHTML(h)),g.css("display","")):g.css("display","none"),f.$setValidity(f.$name,!1),e.inValidCallback&&e.inValidCallback(),!1},g=!1,h=function(a,d,g,i,j,k){var l=j.slice(0),m=l[0].trim(),n=l.slice(1),o=m+"SuccessMessage",p=m+"ErrorMessage",q=b.getExpression(m),r={success:function(){return e(d,g[o],m,a,i),n.length?void h(a,d,g,i,n,k):!0},error:function(){return f(d,g[p],m,a,i)}};if(void 0===q){if(console.error('You are using undefined validator "%s"',m),!n.length)return;h(a,d,g,i,n,k)}return q.constructor===Function?c.all([b.getExpression(m)(k,a,d,g)]).then(function(a){return a&&a.length>0&&a[0]?r.success():r.error()},function(){return r.error()}):q.constructor===RegExp&&void 0!==k&&null!==k&&b.getExpression(m).test(k)?r.success():r.error()},i=function(){return(65536*(1+Math.random())|0).toString(16).substring(1)},j=function(){return i()+i()+i()+i()};return{restrict:"A",require:"ngModel",scope:{model:"=ngModel",initialValidity:"=initialValidity",validCallback:"&",invalidCallback:"&",messageId:"@"},link:function(a,b,c,e){var f,i=function(){},k=c.validator.split(","),l=e.validationId=j();"boolean"==typeof a.initialValidity&&(f=a.initialValidity),a.messageId||b.after(""),e.$setValidity(e.$name,f),a.$on(e.$name+"reset-"+l,function(){i(),g=!1,e.$setViewValue(""),e.$setPristine(),e.$setValidity(e.$name,void 0),e.$render(),a.messageId?angular.element(document.querySelector("#"+a.messageId)).html(""):b.next().html("")}),function(){return a.$on(e.$name+"submit-"+l,function(d,f){var j=e.$viewValue,l=!1;0===f&&(g=!1),l=h(a,b,c,e,k,j),"submit"===c.validMethod&&(i(),i=a.$watch("model",function(d,f){d!==f&&((void 0===d||null===d)&&(d=""),l=h(a,b,c,e,k,d))})),g||l||(g=!0,b[0].focus())}),"blur"===c.validMethod?void b.bind("blur",function(){var d=e.$viewValue;a.$apply(function(){h(a,b,c,e,k,d)})}):void("submit"!==c.validMethod&&"submit-only"!==c.validMethod&&a.$watch("model",function(d){if(e.$pristine&&e.$viewValue)e.$setViewValue(e.$viewValue);else if(e.$pristine)return void(a.messageId?angular.element(document.querySelector("#"+a.messageId)).html(""):b.next().html(""));h(a,b,c,e,k,d)}))}(),d(function(){c.$observe("noValidationMessage",function(c){var d;d=a.messageId?angular.element(document.querySelector("#"+a.messageId)):b.next(),"true"==c||c===!0?d.css("display","none"):("false"==c||c===!1)&&d.css("display","block")})})}}}]).directive("validationSubmit",["$injector",function(a){var b=a.get("$validation"),c=a.get("$timeout"),d=a.get("$parse");return{priority:1,require:"?ngClick",link:function(a,e,f){var g=d(f.validationSubmit)(a);c(function(){e.off("click"),e.on("click",function(c){c.preventDefault(),b.validate(g).success(function(){d(f.ngClick)(a)})})})}}}]).directive("validationReset",["$injector",function(a){var b=a.get("$validation"),c=a.get("$timeout"),d=a.get("$parse");return{link:function(a,e,f){var g=d(f.validationReset)(a);c(function(){e.on("click",function(a){a.preventDefault(),b.reset(g)})})}}}])}.call(this); \ No newline at end of file +(function(){angular.module("validation",["validation.provider","validation.directive"])}).call(this),function(){angular.module("validation.provider",[]).provider("$validation",function(){var a,b,c,d,e,f=this,g=function(f){a=f,b=a.get("$rootScope"),c=a.get("$http"),d=a.get("$q"),e=a.get("$timeout")},h={},i={};this.setExpression=function(a){return angular.extend(h,a),f},this.getExpression=function(a){return h[a]},this.setDefaultMsg=function(a){return angular.extend(i,a),f},this.getDefaultMsg=function(a){return i[a]},this.setErrorHTML=function(a){return a.constructor===Function?(f.getErrorHTML=a,f):void 0},this.getErrorHTML=function(a){return'

'+a+"

"},this.setSuccessHTML=function(a){return a.constructor===Function?(f.getSuccessHTML=a,f):void 0},this.getSuccessHTML=function(a){return'

'+a+"

"},this.showSuccessMessage=!0,this.showErrorMessage=!0,this.checkValid=function(a){return void 0===a.$valid?!1:a&&a.$valid===!0},this.validate=function(a){var c=d.defer(),g=0;if(void 0===a)return console.error("This is not a regular Form name scope"),c.reject("This is not a regular Form name scope"),c.promise;if(a.validationId)b.$broadcast(a.$name+"submit-"+a.validationId,g++);else if(a.constructor===Array)for(var h in a)b.$broadcast(a[h].$name+"submit-"+a[h].validationId,g++);else for(var i in a)"$"!==i[0]&&a[i].hasOwnProperty("$dirty")&&b.$broadcast(i+"submit-"+a[i].validationId,g++);return c.promise.success=function(a){return c.promise.then(function(b){a(b)}),c.promise},c.promise.error=function(a){return c.promise.then(null,function(b){a(b)}),c.promise},e(function(){f.checkValid(a)?c.resolve("success"):c.reject("error")}),c.promise},this.validCallback=null,this.invalidCallback=null,this.reset=function(a){if(void 0===a)return void console.error("This is not a regular Form name scope");if(a.validationId)b.$broadcast(a.$name+"reset-"+a.validationId);else if(a.constructor===Array)for(var c in a)b.$broadcast(a[c].$name+"reset-"+a[c].validationId);else for(var d in a)"$"!==d[0]&&a[d].hasOwnProperty("$dirty")&&b.$broadcast(d+"reset-"+a[d].validationId)},this.$get=["$injector",function(a){return g(a),{setErrorHTML:this.setErrorHTML,getErrorHTML:this.getErrorHTML,setSuccessHTML:this.setSuccessHTML,getSuccessHTML:this.getSuccessHTML,setExpression:this.setExpression,getExpression:this.getExpression,setDefaultMsg:this.setDefaultMsg,getDefaultMsg:this.getDefaultMsg,showSuccessMessage:this.showSuccessMessage,showErrorMessage:this.showErrorMessage,checkValid:this.checkValid,validate:this.validate,validCallback:this.validCallback,invalidCallback:this.invalidCallback,reset:this.reset}}]})}.call(this),function(){angular.module("validation.directive",["validation.provider"]).directive("validator",["$injector",function(a){var b=a.get("$validation"),c=a.get("$q"),d=a.get("$timeout"),e=function(a,c,d,e,f){var g,h=c||b.getDefaultMsg(d).success;return g=e.messageId?angular.element(document.querySelector("#"+e.messageId)):a.next(),b.showSuccessMessage&&h?(g.html(b.getSuccessHTML(h)),g.css("display","")):g.css("display","none"),f.$setValidity(f.$name,!0),e.validCallback&&e.validCallback(),b.validCallback&&b.validCallback(a),!0},f=function(a,c,d,e,f){var g,h=c||b.getDefaultMsg(d).error;return g=e.messageId?angular.element(document.querySelector("#"+e.messageId)):a.next(),b.showErrorMessage&&h?(g.html(b.getErrorHTML(h)),g.css("display","")):g.css("display","none"),f.$setValidity(f.$name,!1),e.inValidCallback&&e.inValidCallback(),b.invalidCallback&&b.invalidCallback(a),!1},g=!1,h=function(a,d,g,i,j,k){var l=j.slice(0),m=l[0].trim(),n=l.slice(1),o=m+"SuccessMessage",p=m+"ErrorMessage",q=b.getExpression(m),r={success:function(){return e(d,g[o],m,a,i),n.length?void h(a,d,g,i,n,k):!0},error:function(){return f(d,g[p],m,a,i)}};if(void 0===q){if(console.error('You are using undefined validator "%s"',m),!n.length)return;h(a,d,g,i,n,k)}return q.constructor===Function?c.all([b.getExpression(m)(k,a,d,g)]).then(function(a){return a&&a.length>0&&a[0]?r.success():r.error()},function(){return r.error()}):q.constructor===RegExp&&void 0!==k&&null!==k&&b.getExpression(m).test(k)?r.success():r.error()},i=function(){return(65536*(1+Math.random())|0).toString(16).substring(1)},j=function(){return i()+i()+i()+i()};return{restrict:"A",require:"ngModel",scope:{model:"=ngModel",initialValidity:"=initialValidity",validCallback:"&",invalidCallback:"&",messageId:"@"},link:function(a,b,c,e){var f,i=function(){},k=c.validator.split(","),l=e.validationId=j();"boolean"==typeof a.initialValidity&&(f=a.initialValidity),a.messageId||b.after(""),e.$setValidity(e.$name,f),a.$on(e.$name+"reset-"+l,function(){i(),g=!1,e.$setViewValue(""),e.$setPristine(),e.$setValidity(e.$name,void 0),e.$render(),a.messageId?angular.element(document.querySelector("#"+a.messageId)).html(""):b.next().html("")}),function(){return a.$on(e.$name+"submit-"+l,function(d,f){var j=e.$viewValue,l=!1;0===f&&(g=!1),l=h(a,b,c,e,k,j),"submit"===c.validMethod&&(i(),i=a.$watch("model",function(d,f){d!==f&&((void 0===d||null===d)&&(d=""),l=h(a,b,c,e,k,d))})),g||l||(g=!0,b[0].focus())}),"blur"===c.validMethod?void b.bind("blur",function(){var d=e.$viewValue;a.$apply(function(){h(a,b,c,e,k,d)})}):void("submit"!==c.validMethod&&"submit-only"!==c.validMethod&&a.$watch("model",function(d){if(e.$pristine&&e.$viewValue)e.$setViewValue(e.$viewValue);else if(e.$pristine)return void(a.messageId?angular.element(document.querySelector("#"+a.messageId)).html(""):b.next().html(""));h(a,b,c,e,k,d)}))}(),d(function(){c.$observe("noValidationMessage",function(c){var d;d=a.messageId?angular.element(document.querySelector("#"+a.messageId)):b.next(),"true"==c||c===!0?d.css("display","none"):("false"==c||c===!1)&&d.css("display","block")})})}}}]).directive("validationSubmit",["$injector",function(a){var b=a.get("$validation"),c=a.get("$timeout"),d=a.get("$parse");return{priority:1,require:"?ngClick",link:function(a,e,f){var g=d(f.validationSubmit)(a);c(function(){e.off("click"),e.on("click",function(c){c.preventDefault(),b.validate(g).success(function(){d(f.ngClick)(a)})})})}}}]).directive("validationReset",["$injector",function(a){var b=a.get("$validation"),c=a.get("$timeout"),d=a.get("$parse");return{link:function(a,e,f){var g=d(f.validationReset)(a);c(function(){e.on("click",function(a){a.preventDefault(),b.reset(g)})})}}}])}.call(this); \ No newline at end of file