Skip to content
This repository was archived by the owner on Jul 1, 2020. It is now read-only.

Commit 2d71a7e

Browse files
committed
Fixed bug #16 reset ValidationSummary route change
- Added option to display only last error message instead of all messages at once - Added new template to display ngRepeat examples, also help troubleshooting the follwoing bug. - Fixed a bug (probably linked to issue #16) where changing route on View/Controller would make the ValidationSummary fail when coming back to original View/Controller, this bug was associated to the fact that the ValidationSummary kept growing from Controller to Controller, now this ValidationSummary is wipe out as soon as we detect a route change.
1 parent 76fcaff commit 2d71a7e

12 files changed

+170
-63
lines changed

app.js

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,11 @@ var myApp = angular.module('myApp', ['ngRoute', 'ghiscoding.validation', 'pascal
55
myApp.config(['$compileProvider', '$locationProvider', '$routeProvider', function ($compileProvider, $locationProvider, $routeProvider) {
66
$compileProvider.debugInfoEnabled(false);
77
$routeProvider
8-
.when('/validate-directive', {
9-
templateUrl: 'templates/testingFormDirective.html',
10-
controller: 'CtrlValidationDirective'
11-
})
12-
.when('/validate-2forms', {
13-
templateUrl: 'templates/testing2Forms.html',
14-
controller: 'Ctrl2forms'
15-
})
16-
.when('/validate-service', {
17-
templateUrl: 'templates/testingFormService.html',
18-
controller: 'CtrlValidationService'
19-
})
20-
.otherwise({
21-
redirectTo: 'validate-directive',
22-
});
8+
.when('/validate-directive', { templateUrl: 'templates/testingFormDirective.html', controller: 'CtrlValidationDirective' })
9+
.when('/validate-2forms', { templateUrl: 'templates/testing2Forms.html', controller: 'Ctrl2forms' })
10+
.when('/validate-ngRepeat', { templateUrl: 'templates/testingFormNgRepeat.html', controller: 'CtrlNgRepeat' })
11+
.when('/validate-service', { templateUrl: 'templates/testingFormService.html', controller: 'CtrlValidationService' })
12+
.otherwise({ redirectTo: 'validate-directive' });
2313
}])
2414
.config(['$translateProvider', function ($translateProvider) {
2515
$translateProvider.useStaticFilesLoader({
@@ -135,4 +125,24 @@ myApp.controller('CtrlValidationService', ['$scope', '$translate', 'validationSe
135125
alert('All good, proceed with submit...');
136126
}
137127
}
128+
}]);
129+
130+
// -- Controller to use Angular-Validation with Directive and ngRepeat
131+
// ---------------------------------------------------------------
132+
myApp.controller('CtrlNgRepeat', ['$scope', 'validationService', function ($scope, validationService) {
133+
// Form data
134+
$scope.people = [
135+
{ name: 'John', age: 20 },
136+
{ name: 'Jane', age: null },
137+
{ name: null, age: null }
138+
];
139+
140+
$scope.submitForm = function() {
141+
if(new validationService().checkFormValidity($scope.form01)) {
142+
alert('All good, proceed with submit...');
143+
}
144+
}
145+
$scope.showValidationSummary = function () {
146+
$scope.displayValidationSummary = true;
147+
}
138148
}]);

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "angular-validation-ghiscoding",
3-
"version": "1.3.22",
3+
"version": "1.3.23",
44
"author": "Ghislain B.",
55
"description": "Angular-Validation Directive and Service (ghiscoding)",
66
"main": [

changelog.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ Angular-Validation change logs
2323
1.3.19 (2015-04-20) Fixed issue #28 - unbind all 'blur' in cancelValidation() might affect other modules
2424
1.3.20 (2015-04-21) Fixed issue #26 - validation of forms inside ng-repeat (added sample `dynamicFormView` in `more-examples` folder). And again issue #28 - unbind all 'blur' in cancelValidation() might affect other modules.
2525
1.3.21 (2015-04-29) Moved the Alternate Text inside the $translate promise as well which removes possible delay of non-translated text appearing as alternate text (this will not affect regular text, or already translated text). Also cleanup code and made my Gulp task even more automated.
26-
1.3.22 (2015-05-03) Added new element attribute of `friendly-name` which is used ONLY in the ValidationSummary, this friendly name is to give a better element name display, which also support translation, inside the ValidationSummary instead of just "input1" (see ValidationSummary for more details).
26+
1.3.22 (2015-05-03) Added new element attribute of `friendly-name` which is used ONLY in the ValidationSummary, this friendly name is to give a better element name display, which also support translation, inside the ValidationSummary instead of just "input1" (see ValidationSummary for more details).
27+
1.3.23 (2015-05-05) Added option to display only last error message instead of all messages at once. Fixed a bug where changing route on View/Controller would make the ValidationSummary fail when coming back to original View/Controller, this bug was associated to the fact that the ValidationSummary kept growing from Controller to Controller, now this ValidationSummary is wipe out as soon as we detect a route change.

dist/angular-validation.min.js

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gulpfile.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ gulp.task('compress', ['clean'], function() {
6969
// bump version for js file header
7070
newVersion = semver.inc(oldVersion, 'patch');
7171

72-
// bump version in package & bower
72+
// bump version for both: package & bower
7373
gulp.src(['./package.json', './bower.json'])
7474
.pipe(bump())
7575
.pipe(gulp.dest('./'));

index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ <h1>Angular-Validation Directive|Service (ghiscoding)</h1>
2929
<button type="button" class="btn btn-default" ng-click="goto('/validate-directive')">Directive</button>
3030
<button type="button" class="btn btn-default" ng-click="goto('/validate-service')">Service</button>
3131
<button type="button" class="btn btn-default" ng-click="goto('/validate-2forms')">2 Forms</button>
32+
<button type="button" class="btn btn-default" ng-click="goto('/validate-ngRepeat')">ngRepeat</button>
3233
</div>
3334

3435
<br/><hr/>

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "angular-validation-ghiscoding",
3-
"version": "1.3.22",
3+
"version": "1.3.23",
44
"author": "Ghislain B.",
55
"description": "Angular-Validation Directive and Service (ghiscoding)",
66
"main": "app.js",

readme.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#Angular Validation (Directive / Service)
2-
`Version: 1.3.22`
2+
`Version: 1.3.23`
33
### Form validation after user inactivity of default 1sec. (customizable timeout)
44

55
Forms Validation with Angular made easy! Angular-Validation is an angular directive/service with locales (languages) with a very simple approach of defining your `validation=""` directly within your element to validate (input, textarea, etc) and...that's it!!! The directive/service will take care of the rest!
@@ -8,7 +8,7 @@ The base concept is not new, it comes from the easy form input validation approa
88

99
For a smoother user experience, I also added validation on inactivity (timer/debounce). So validation will not bother the user while he is still typing... though as soon as the user pauses for a certain amount of time, then validation comes into play. It's worth knowing that this inactivity timer is only available while typing, if user focuses away from his input (onBlur) it will then validate instantly.
1010

11-
Supporting AngularJS 1.3.x *(current code should work with 1.2.x just the same but is no more verified)*
11+
Supporting AngularJS 1.3.x *(current code should work with 1.2.x just the same, but is no more verified)*
1212

1313
Now support <b>Service</b> using the same functionalities as the <b>Directive</b>.
1414
Huge rewrite to have a better code separation and also adding support to Service functionalities. Specifically the `validation-rules` was separated to add rules without affecting the core while `validation-common` is for shared functions (shared by Directive/Service).
@@ -17,7 +17,7 @@ Huge rewrite to have a better code separation and also adding support to Service
1717

1818
For more reasons to use it, see the answered question of: [Why Use It?](#whyuseit)
1919

20-
If you do use it, please click on the Star and add it as a favourite. The more star ratings there is, the more chances it could found by other users as a populate trend. That is the only support I ask you... thanks ;)
20+
If you do use Angular-Validation, please click on the **Star** and add it as a favourite. The more star ratings there is, the more chances it could found by other users inside the popular trend section. That is the only support I ask you... thanks ;)
2121

2222
<a name="plunker"></a>
2323
## Live Demo
@@ -51,7 +51,7 @@ into the following (errors will be displayed in your chosen locale translation):
5151
<input type="text" name="firstname" ng-model="user.firstname" validation="alpha_dash|min_len:3|max_len:50|required" />
5252
<input type="text" name="lastname" ng-model="user.lastname" validation="alpha_dash|min_len:2|max_len:50|required" />
5353
```
54-
The Angular-Validation will create, by itself, the necessary error message. Now imagine your form with 10 inputs, using the Angular-Validation will end up using 10 lines of code, while on the other hand using the default of Angular will give you 30 lines of code... so what are you waiting for? Use Angular-Validation!!! :)
54+
The Angular-Validation will create, by itself, the necessary error message. Now imagine your form having 10 inputs, using the documented Angular way will end up being 30 lines of code, while on the other hand `Angular-Validation` will stay with 10 lines of code, no more... so what are you waiting for? Use Angular-Validation!!! Don't forget to add it to your favorite, click on the **Star** :)
5555

5656
Let's not forget the [Validation Summary](/ghiscoding/angular-validation/wiki/Validation-Summary) which is also a great and useful way of displaying your errors to the user.
5757

src/validation-common.js

Lines changed: 66 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,35 @@
44
*
55
* @author: Ghislain B.
66
* @desc: angular-validation common functions used by both the Directive & Service
7-
* From the outside we will define our complete validation through: defineValidation()
87
*
98
*/
109
angular
1110
.module('ghiscoding.validation')
12-
.factory('validationCommon', ['$timeout', '$translate', 'validationRules', function ($timeout, $translate, validationRules) {
11+
.factory('validationCommon', ['$rootScope', '$timeout', '$translate', 'validationRules', function ($rootScope, $timeout, $translate, validationRules) {
1312
// global variables of our object
14-
var bFieldRequired = false; // by default we'll consider our field not required, if validation attribute calls it, then we'll start validating
15-
var INACTIVITY_LIMIT = 1000; // constant of maximum user inactivity time limit, this is the default cosntant but can be variable through typingLimit variable
16-
17-
var elm; // element object of current form element
18-
var ctrl; // ctrl object of the current form element
19-
var scope; // scope object of the current form element
20-
var value; // value of current form element
21-
var timer; // timer of user inactivity time
22-
var typingLimit; // maximum user inactivity typing limit
23-
var formElements = []; // Array of all Form Elements, this is not a DOM Elements, these are custom objects defined as { fieldName, elm, attrs, ctrl, isValid, message }
24-
var validators = []; // Array of all Form Validators
25-
var validatorAttrs = {}; // Current Validator attributes
26-
var validationSummary = []; // Array Validation Error Summary
13+
var bypassRootScopeReset = false; // do we want to bypass the watch on the $rootScope? False by default
14+
var bDisplayOnlyLastErrorMsg = false; // display only 1 error message at a time, by default it's false since we will display all errors of each element
15+
var bFieldRequired = false; // by default we'll consider our field not required, if validation attribute calls it, then we'll start validating
16+
var INACTIVITY_LIMIT = 1000; // constant of maximum user inactivity time limit, this is the default cosntant but can be variable through typingLimit variable
17+
18+
var elm; // element object of current form element
19+
var ctrl; // ctrl object of the current form element
20+
var scope; // scope object of the current form element
21+
var value; // value of current form element
22+
var timer; // timer of user inactivity time
23+
var typingLimit; // maximum user inactivity typing limit
24+
var formElements = []; // Array of all Form Elements, this is not a DOM Elements, these are custom objects defined as { fieldName, elm, attrs, ctrl, isValid, message }
25+
var validators = []; // Array of all Form Validators
26+
var validatorAttrs = {}; // Current Validator attributes
27+
var validationSummary = []; // Array Validation Error Summary
28+
29+
// watch on route change, then reset some global variables, so that we don't cary over other controller/view validations
30+
$rootScope.$on("$routeChangeStart", function (event, next, current) {
31+
if (!bypassRootScopeReset) {
32+
formElements = []; // array containing all form elements, valid or invalid
33+
validationSummary = []; // array containing the list of invalid fields inside a validationSummary
34+
}
35+
});
2736

2837
// service constructor
2938
var validationCommon = function(scope, elm, attrs, ctrl) {
@@ -45,15 +54,17 @@ angular
4554
};
4655

4756
// list of available published public functions of this object
48-
validationCommon.prototype.defineValidation = defineValidation; // define our validation object
49-
validationCommon.prototype.getFormElementByName = getFormElementByName; // get the form element custom object by it's name
50-
validationCommon.prototype.getFormElements = getFormElements; // get the array of form elements (custom objects)
51-
validationCommon.prototype.isFieldRequired = isFieldRequired; // return boolean knowing if the current field is required
52-
validationCommon.prototype.initialize = initialize; // initialize current object with passed arguments
53-
validationCommon.prototype.updateErrorMsg = updateErrorMsg; // update on screen an error message below current form element
54-
validationCommon.prototype.validate = validate; // validate current element
55-
validationCommon.prototype.removeFromValidationSummary = removeFromValidationSummary; // remove an element from the $validationSummary
56-
validationCommon.prototype.removeFromFormElementObjectList = removeFromFormElementObjectList; // remove named items from formElements list
57+
validationCommon.prototype.defineValidation = defineValidation; // define our validation object
58+
validationCommon.prototype.getFormElementByName = getFormElementByName; // get the form element custom object by it's name
59+
validationCommon.prototype.getFormElements = getFormElements; // get the array of form elements (custom objects)
60+
validationCommon.prototype.isFieldRequired = isFieldRequired; // return boolean knowing if the current field is required
61+
validationCommon.prototype.initialize = initialize; // initialize current object with passed arguments
62+
validationCommon.prototype.removeFromValidationSummary = removeFromValidationSummary; // remove an element from the $validationSummary
63+
validationCommon.prototype.removeFromFormElementObjectList = removeFromFormElementObjectList; // remove named items from formElements list
64+
validationCommon.prototype.setBypassRootScopeReset = setBypassRootScopeReset; // setter on: do we want to bypass the root scope reset?
65+
validationCommon.prototype.setDisplayOnlyLastErrorMsg = setDisplayOnlyLastErrorMsg; // setter on the behaviour of displaying only the last error message
66+
validationCommon.prototype.updateErrorMsg = updateErrorMsg; // update on screen an error message below current form element
67+
validationCommon.prototype.validate = validate; // validate current element
5768

5869
// return the service object
5970
return validationCommon;
@@ -188,6 +199,23 @@ angular
188199
}
189200
}
190201

202+
/** Setter on the action of bypassing the root scope reset, you can change the default behavior with this function here.
203+
* Explanation: By default a route change will trigger a reset of some global variables (formElements, validationSummary),
204+
* so that we don't see validations of previous routes or controllers.
205+
* @param boolean value
206+
*/
207+
function setBypassRootScopeReset(boolValue) {
208+
bypassRootScopeReset = boolValue;
209+
}
210+
211+
/** Setter on the behaviour of displaying only the last error message of each element.
212+
* By default this is false, so the behavior is to display all error messages of each element.
213+
* @param boolean value
214+
*/
215+
function setDisplayOnlyLastErrorMsg(boolValue) {
216+
bDisplayOnlyLastErrorMsg = boolValue;
217+
}
218+
191219
/** in general we will display error message at the next element after our input as <span class="validation validation-inputName text-danger">
192220
* but in some cases user might want to define which DOM id to display error (as validation attribute)
193221
* @param string message: error message to display
@@ -354,15 +382,25 @@ angular
354382
msgToTranslate = validator.altText.replace("alt=", "");
355383
}
356384

357-
$translate(msgToTranslate).then(function(translation) {
358-
message += ' ' + replaceParams(validator, translation);
385+
$translate(msgToTranslate).then(function (translation) {
386+
// if user is requesting to see only the last error message
387+
if (message.length > 0 && bDisplayOnlyLastErrorMsg) {
388+
message = ' ' + replaceParams(validator, translation);
389+
} else {
390+
message += ' ' + replaceParams(validator, translation);
391+
}
359392
addToValidationAndDisplayError(self, formElmObj, message, isFieldValid, showError);
360393
}).catch(function(data) {
361394
// error caught:
362395
// alternate text might not need translation if the user sent his own custom message or is already translated
363396
// so just send it directly into the validation summary.
364-
if(!!validator.altText && validator.altText.length > 0) {
365-
message += ' ' + msgToTranslate;
397+
if (!!validator.altText && validator.altText.length > 0) {
398+
// if user is requesting to see only the last error message
399+
if (message.length > 0 && bDisplayOnlyLastErrorMsg) {
400+
message = ' ' + msgToTranslate;
401+
} else {
402+
message += ' ' + msgToTranslate;
403+
}
366404
addToValidationAndDisplayError(self, formElmObj, message, isFieldValid, showError);
367405
}
368406
});

0 commit comments

Comments
 (0)