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

Commit b1a6095

Browse files
committed
Fixed issue #26 dynamic form and #28
- Added sample of issue #26 - Fixed issue #26 - validation of dynamic forms inside ng-repeat - Fixed again issue #28 - unbind all 'blur' in cancelValidation() might affect other modules.
1 parent 2c1e5d6 commit b1a6095

15 files changed

+190
-51
lines changed

bower.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ghiscoding.angular-validation",
3-
"version": "1.3.19",
3+
"version": "1.3.20",
44
"authors": [
55
"Ghislain B."
66
],
@@ -30,6 +30,10 @@
3030
"tests",
3131
"more-examples",
3232
"templates",
33+
"app.js",
34+
"changelog.txt",
35+
"index.html",
36+
"gulpfile.js",
3337
"vendors",
3438
"README.md"
3539
],

changelog.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ Angular-Validation change logs
2020
1.3.16 (2015-04-09) Accept Merge #3 Fixed removeFromValidationSummary to also remove from 'local' array
2121
1.3.17 (2015-04-11) Added global `$scope.$validationOptions` object, for now only has the `debounce` property that be used by both the Directive and Service.
2222
1.3.18 (2015-04-19) Fixed issue #20 - Error messages shown on submit are non-understandable, this was fixed using $translate promises instead of $translate.instant(). Fixed a few error display on the validationSummary() and checkFormValidity(). Also merged #27 to add Russian
23-
1.3.19 (2015-04-20) Fixed issue #28 - unbind all 'blur' in cancelValidation() might affect other modules
23+
1.3.19 (2015-04-20) Fixed issue #28 - unbind all 'blur' in cancelValidation() might affect other modules
24+
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.

dist/angular-validation.min.js

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

more-examples/dynamicForm-app.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
'use strict';
2+
3+
var app = angular.module('plunker', ['ui.bootstrap','ghiscoding.validation', 'pascalprecht.translate']);
4+
5+
app.config(['$translateProvider', function ($translateProvider) {
6+
$translateProvider.useStaticFilesLoader({
7+
prefix: '../locales/validation/',
8+
suffix: '.json'
9+
});
10+
11+
// load English ('en') table on startup
12+
$translateProvider.preferredLanguage('en');
13+
}]);
14+
15+
app.directive('formField',function(){
16+
return{
17+
restrict:'E',
18+
templateUrl:"dynamicFormView.html"
19+
}
20+
});
21+
22+
app.controller('MainCtrl', function($scope,validationService) {
23+
$scope.name = 'World';
24+
$scope.items={};
25+
$scope.items.item1={
26+
heading:"Item1",
27+
formName:"Form1"
28+
};
29+
$scope.items.item1.fields=[
30+
{
31+
name: 'firstName',
32+
label:'Enter First Name',
33+
validation:"required"
34+
},
35+
{
36+
name: 'lastName',
37+
label: 'Enter Last Name',
38+
validation:"required"
39+
}
40+
];
41+
$scope.items.item2={
42+
heading:"Item2",
43+
formName:"Form2"
44+
};
45+
$scope.items.item2.fields=[
46+
{
47+
name: 'email',
48+
label:'Enter Email Id',
49+
validation:"required"
50+
},
51+
{
52+
name: 'phoneNo',
53+
label: 'Enter Phone Number',
54+
validation:"required"
55+
}
56+
];
57+
58+
$scope.validate=function(){
59+
for(var key in $scope.items){
60+
var formName=$scope.items[key].formName;
61+
var form = angular.element(document.querySelector('[name="'+formName+'"]'));
62+
var childScope = form.scope();
63+
console.debug(childScope[formName]);
64+
if(new validationService().checkFormValidity(childScope[formName]))
65+
alert("form "+formName+" is valid");
66+
else
67+
alert("form "+formName+" is invalid");
68+
}
69+
};
70+
});

more-examples/dynamicFormIndex.html

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<!DOCTYPE html>
2+
<html ng-app="plunker">
3+
4+
<head>
5+
<meta charset="utf-8" />
6+
<title>AngularJS Plunker</title>
7+
<script>document.write('<base href="' + document.location + '" />');</script>
8+
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
9+
<link rel="stylesheet" href="../style.css">
10+
11+
<!-- external librairies CDN -->
12+
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
13+
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-route.js"></script>
14+
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.1.js"></script>
15+
16+
<!-- angular-translate -->
17+
<!-- Visit Angular-Translate https://github.com/PascalPrecht/angular-translate -->
18+
<script src="../vendors/angular-translate/angular-translate.min.js"></script>
19+
<script src="../vendors/angular-translate/angular-translate-loader-static-files.min.js"></script>
20+
21+
<!-- Angular-Validation -->
22+
<!--<script type="text/javascript" src="../dist/angular-validation.min.js"></script>-->
23+
<script type="text/javascript" src="../src/validation-directive.js"></script>
24+
<script type="text/javascript" src="../src/validation-service.js"></script>
25+
<script type="text/javascript" src="../src/validation-common.js"></script>
26+
<script type="text/javascript" src="../src/validation-rules.js"></script>
27+
28+
<script src="dynamicForm-app.js"></script>
29+
</head>
30+
31+
<body ng-controller="MainCtrl">
32+
<h3>Form Validation (with dynamic form and fields)</h3>
33+
<tabset>
34+
<tab ng-repeat="tab in items" heading="{{tab.heading}}" >
35+
<form name="{{tab.formName}}" novalidate>
36+
<div ng-repeat="field in tab.fields" >
37+
<form-field></form-field>
38+
</div>
39+
</form>
40+
</tab>
41+
</tabset>
42+
<button name="validateForms" value="Validate" ng-click="validate()">Validate</button>
43+
</body>
44+
45+
</html>

more-examples/dynamicFormView.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<label class="topMargin leftColumn" for="{{field.name}}">{{field.label}} : </label>
2+
<input class="topMargin leftMargin" validation="{{field.validation}}" ng-model="values[field.name]" name="{{field.name}}" type="text">

more-examples/dynamic-app.js renamed to more-examples/dynamicInput-app.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ var myApp = angular.module('myApp', ['ngRoute', 'pascalprecht.translate', 'ghisc
44

55
myApp.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
66
$routeProvider.when('/dynamic', {
7-
templateUrl: 'dynamicForm.html',
7+
templateUrl: 'dynamicInputTemplate.html',
88
controller: 'CtrlDynamic'
99
});
1010
$routeProvider.otherwise({
@@ -27,19 +27,23 @@ myApp.config(['$routeProvider', '$locationProvider', function ($routeProvider, $
2727
$translate.use(key);
2828
};
2929

30-
$scope.data = [{
30+
$scope.data = [
31+
{
3132
'name': "abc",
3233
'title': 'first',
3334
'validate':"required"
34-
}, {
35+
},
36+
{
3537
'name': "xyz",
3638
'title': 'second',
3739
'validate':"max_len:12|required"
38-
}, {
40+
},
41+
{
3942
'name': "std",
4043
'title': 'third',
4144
'validate':"max_len:22|required"
42-
}];
45+
}
46+
];
4347
}])
4448
.directive('dyninp', [ function () {
4549
return {

more-examples/dynamicIndex.html renamed to more-examples/dynamicInputIndex.html

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,14 @@ <h3 class="text-info">{{'CHANGE_LANGUAGE' | translate}}</h3>
3232
<script src="../vendors/angular-translate/angular-translate-loader-static-files.min.js"></script>
3333

3434
<!-- Angular-Validation -->
35-
<script type="text/javascript" src="../dist/angular-validation.min.js"></script>
35+
<!--<script type="text/javascript" src="../dist/angular-validation.min.js"></script>-->
36+
<script type="text/javascript" src="../src/validation-directive.js"></script>
37+
<script type="text/javascript" src="../src/validation-service.js"></script>
38+
<script type="text/javascript" src="../src/validation-common.js"></script>
39+
<script type="text/javascript" src="../src/validation-rules.js"></script>
3640

3741
<!-- my application -->
38-
<script type="text/javascript" src="dynamic-app.js"></script>
42+
<script type="text/javascript" src="dynamicInput-app.js"></script>
3943
</div>
4044
</body>
4145
</html>

package.json

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

readme.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#Angular Validation (Directive / Service)
2-
`Version: 1.3.19`
2+
`Version: 1.3.20`
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!
@@ -500,4 +500,5 @@ License
500500
* [1.3.16](https://github.com/ghiscoding/angular-validation/commit/6c419d45bdb00341416d91199003d827259bd5da) `2015-04-09` Accept Merge #3 Fixed removeFromValidationSummary to also remove from 'local' array
501501
* [1.3.17](https://github.com/ghiscoding/angular-validation/commit/1283a3a7435c70ec0a355ee273c8479e4b9bdabf) `2015-04-11` Added global `$scope.$validationOptions` [Global Options](#global-options) object, for now only has the `debounce` property that be used by both the Directive and Service.
502502
* [1.3.18](https://github.com/ghiscoding/angular-validation/commit/d4b55741b9635cd5654f44c58c146f4d86b2e512) `2015-04-19` Fixed issue #20 - Error messages shown on submit are non-understandable, this was fixed using $translate promises instead of $translate.instant(). Fixed a few error display on the validationSummary() and checkFormValidity(). Also merged #27 to add Russian
503-
* [1.3.19]() `2015-04-20` Fixed issue #28 - unbind all 'blur' in cancelValidation() might affect other modules
503+
* [1.3.19](https://github.com/ghiscoding/angular-validation/commit/2c1e5d62e434da24c122a5b575b5434e988ff254) `2015-04-20` Fixed issue #28 - unbind all 'blur' in cancelValidation() might affect other modules
504+
* [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.

src/validation-common.js

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,12 @@ angular
262262
var validator;
263263

264264
// get some common variables
265-
var elmName = self.elm.attr('name');
265+
var elmName = (!!self.validatorAttrs && !!self.validatorAttrs.name)
266+
? self.validatorAttrs.name
267+
: (!!self.attrs && !!self.attrs.name)
268+
? self.attrs.name
269+
: self.elm.attr('name');
270+
266271
var formElmObj = getFormElementByName(elmName);
267272
var rules = self.validatorAttrs.hasOwnProperty('rules') ? self.validatorAttrs.rules : self.validatorAttrs.validation;
268273

@@ -349,7 +354,7 @@ angular
349354
addToValidationSummary(self, message.trim());
350355
}else {
351356
// run $translate promise, use closures to keep access to all necessary variables
352-
(function(elmName,isValid, validator) {
357+
(function(formElmObj, isValid, validator) {
353358
$translate(validator.message).then(function(translation) {
354359
message += ' ' + replaceParams(validator, translation);
355360
message = message.trim();
@@ -365,11 +370,13 @@ angular
365370
// error Display
366371
if(showError && !formElmObj.isValid) {
367372
self.updateErrorMsg(message, { isValid: isFieldValid });
368-
}else if(formElmObj.isValid) {
373+
}else if(!!formElmObj && formElmObj.isValid) {
369374
addToValidationSummary(formElmObj, '');
370375
}
376+
}, function(data) {
377+
throw 'Failed to translate' + data;
371378
});
372-
})(elmName,isValid, validator);
379+
})(formElmObj, isValid, validator);
373380
}
374381
}
375382
} // for() loop
@@ -400,7 +407,8 @@ angular
400407
* @param object ctrl
401408
*/
402409
function addToFormElementObjectList(elm, attrs, ctrl, scope) {
403-
var formElm = { fieldName: elm.attr('name'), elm: elm, attrs: attrs, ctrl: ctrl, scope: scope, isValid: false, message: '' };
410+
var elmName = (!!attrs.name) ? attrs.name : elm.attr('name');
411+
var formElm = { fieldName: elmName, elm: elm, attrs: attrs, ctrl: ctrl, scope: scope, isValid: false, message: '' };
404412
var index = arrayFindObjectIndex(formElements, 'fieldName', elm.attr('name')); // find index of object in our array
405413
if(index >= 0) {
406414
formElements[index] = formElm;
@@ -415,8 +423,14 @@ angular
415423
* @param string message: error message
416424
*/
417425
function addToValidationSummary(self, message) {
418-
var elmName = self.elm.attr('name');
419-
var form = getElementParentForm(self); // find the parent form (only found if it has a name)
426+
// get the element name, whichever we find it
427+
var elmName = (!!self.validatorAttrs && !!self.validatorAttrs.name)
428+
? self.validatorAttrs.name
429+
: (!!self.attrs && !!self.attrs.name)
430+
? self.attrs.name
431+
: self.elm.attr('name');
432+
433+
var form = getElementParentForm(elmName, self); // find the parent form (only found if it has a name)
420434
var index = arrayFindObjectIndex(validationSummary, 'field', elmName); // find index of object in our array
421435

422436
// if message is empty, remove it from the validation summary
@@ -495,9 +509,8 @@ angular
495509
* @param object self
496510
* @return object scope form
497511
*/
498-
function getElementParentForm(self) {
512+
function getElementParentForm(elmName, self) {
499513
// from the element passed, get his parent form
500-
var elmName = self.elm.attr('name');
501514
var forms = document.getElementsByName(elmName);
502515

503516
for (var i = 0; i < forms.length; i++) {
@@ -509,21 +522,6 @@ angular
509522
return null;
510523
}
511524

512-
/** Get form within scope (if found)
513-
* @param object self
514-
* @return object scope form
515-
*/
516-
function getScopeForm(self) {
517-
var forms = document.querySelectorAll('form');
518-
for (var i = 0; i < forms.length; i++) {
519-
var form = document.querySelectorAll('form')[i];
520-
if (form && form.name && self.scope[form.name]) {
521-
return self.scope[form.name];
522-
}
523-
}
524-
return null;
525-
}
526-
527525
/** Parse a date from a String and return it as a Date Object to be valid for all browsers following ECMA Specs
528526
* Date type ISO (default), US, UK, Europe, etc... Other format could be added in the switch case
529527
* @param String dateStr: date String

src/validation-directive.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@
5555
$timeout.cancel(timer);
5656
commonObj.updateErrorMsg('');
5757
ctrl.$setValidity('validation', true);
58-
elm.unbind('blur', blurHandler); // unbind onBlur event so that it does not fail on a non-required element that is now dirty & empty
58+
59+
// unbind onBlur handler (if found) so that it does not fail on a non-required element that is now dirty & empty
60+
if(typeof blurHandler !== "undefined") {
61+
elm.unbind('blur', blurHandler);
62+
}
5963
}
6064

6165
/** Validator function to attach to the element, this will get call whenever the input field is updated
@@ -83,13 +87,10 @@
8387
// if field is not required and his value is empty, cancel validation and exit out
8488
// onBlur make validation without waiting
8589
elm.bind('blur', blurHandler = function() {
86-
if(isValidationCancelled) {
87-
return value;
88-
}else {
90+
if(!isValidationCancelled) {
8991
// make the regular validation of the field value
9092
scope.$evalAsync( ctrl.$setValidity('validation', commonObj.validate(value, true)) );
9193
}
92-
return value;
9394
});
9495

9596
// if a field holds invalid characters which are not numbers inside an `input type="number"`, then it's automatically invalid

src/validation-service.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,16 @@ angular
6666
return self;
6767
}
6868

69+
// copy the element attributes name to use throughout validationCommon
70+
// when using dynamic elements, we might have encounter unparsed or uncompiled data, we need to get Angular result with $interpolate
71+
if(new RegExp("{{(.*?)}}").test(attrs.elmName)) {
72+
attrs.elmName = $interpolate(attrs.elmName)(attrs.scope);
73+
}
74+
attrs.name = attrs.elmName;
75+
6976
// onBlur make validation without waiting
7077
attrs.elm.bind('blur', blurHandler = function(event) {
71-
if(isValidationCancelled) {
72-
return;
73-
}else {
78+
if(!isValidationCancelled) {
7479
// re-initialize to use current element & remove waiting time & validate
7580
self.commonObj.initialize(attrs.scope, attrs.elm, attrs, attrs.ctrl);
7681
self.commonObj.typingLimit = 0;
@@ -258,7 +263,11 @@ angular
258263
$timeout.cancel(self.timer);
259264
obj.commonObj.updateErrorMsg('');
260265
obj.commonObj.ctrl.$setValidity('validation', true);
261-
obj.commonObj.elm.unbind('blur', blurHandler); // unbind onBlur event so that it does not fail on a non-required element that is now dirty & empty
266+
267+
// unbind onBlur handler (if found) so that it does not fail on a non-required element that is now dirty & empty
268+
if(typeof blurHandler !== "undefined") {
269+
obj.commonObj.elm.unbind('blur', blurHandler);
270+
}
262271
}
263272

264273
/**

templates/testingFormDirective.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ <h4><strong>{{ 'ERRORS' | translate }}!</strong></h4>
9898
</div>
9999
<div class="form-group">
100100
<label for="input17">{{ 'INPUT18' | translate }}</label>
101-
<input type="text" class="form-control" name="input18" placeholder="date_iso_min:2001-01-01|required" ng-model="input18" validation="date_iso_min:1999-12-31|required" />
101+
<input type="text" class="form-control" name="input18" placeholder="date_iso_min:2001-01-01|required" ng-model="input18" validation="date_iso_min:2001-01-01|required" />
102102
</div>
103103
<div class="form-group">
104104
<label for="input17">{{ 'INPUT19' | translate }}</label>

0 commit comments

Comments
 (0)