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

Commit f6c23f0

Browse files
committed
Enhancement #47 - ControllerAs syntax and fixed #48
- Enhancement #47 - New option to use the ControllerAs syntax. - Also fixed issue #48
1 parent 3ae7555 commit f6c23f0

11 files changed

+133
-60
lines changed

app.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ myApp.config(['$compileProvider', '$locationProvider', '$routeProvider', functio
66
$compileProvider.debugInfoEnabled(false);
77
$routeProvider
88
.when('/validate-directive', { templateUrl: 'templates/testingFormDirective.html', controller: 'CtrlValidationDirective' })
9-
.when('/validate-2forms', { templateUrl: 'templates/testing2Forms.html', controller: 'Ctrl2forms' })
9+
.when('/validate-2forms', { templateUrl: 'templates/testing2Forms.html', controller: 'Ctrl2forms as vm' })
1010
.when('/validate-ngRepeat', { templateUrl: 'templates/testingFormNgRepeat.html', controller: 'CtrlNgRepeat' })
1111
.when('/validate-service', { templateUrl: 'templates/testingFormService.html', controller: 'CtrlValidationService' })
1212
.otherwise({ redirectTo: 'validate-directive' });
@@ -80,21 +80,24 @@ myApp.controller('CtrlValidationDirective', ['$q', '$scope', 'validationService'
8080
}]);
8181

8282
// -- Controller to use Angular-Validation Directive with 2 forms
83+
// on this page we will pre-validate the form and show all errors on page load
8384
// ---------------------------------------------------------------
8485
myApp.controller('Ctrl2forms', ['$scope', 'validationService', function ($scope, validationService) {
85-
// on this page we will pre-validate the form and show all errors on page load
86-
$scope.$validationOptions = { debounce: 500, preValidateFormElements: true };
86+
var vm = this; // use the ControllerAs alias syntax
8787

88-
$scope.submitForm = function() {
89-
if(new validationService().checkFormValidity($scope.form01)) {
88+
// set the global options BEFORE any function declarations, we will prevalidate current form
89+
var myValidationService = new validationService({ controllerAs: vm, debounce: 500, preValidateFormElements: true });
90+
91+
vm.submitForm = function() {
92+
if(myValidationService.checkFormValidity(vm.form01)) {
9093
alert('All good, proceed with submit...');
9194
}
9295
}
93-
$scope.resetForm = function(form) {
94-
new validationService().resetForm(form, { emptyAllInputValues: true, removeAllValidators: true });
96+
vm.resetForm = function(form) {
97+
myValidationService.resetForm(form, { emptyAllInputValues: true, removeAllValidators: true });
9598
};
96-
$scope.showValidationSummary = function () {
97-
$scope.displayValidationSummary = true;
99+
vm.showValidationSummary = function () {
100+
vm.displayValidationSummary = true;
98101
}
99102
}]);
100103

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.35",
3+
"version": "1.3.36",
44
"author": "Ghislain B.",
55
"description": "Angular-Validation Directive and Service (ghiscoding)",
66
"main": [

changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
Angular-Validation change logs
22

3+
1.3.36 (2015-07-20) Enhancement #47 - New option to use the ControllerAs syntax. Also fixed issue #48.
34
1.3.35 (2015-07-15) Deprecated old implentation of `regex:...:regex` (though it still works) by a new and much better implementation of `pattern=` validator. Converted all the rules from string pattern to regex pattern (when possible) defined in `angular-validation.js`. Also fixed issue #45 on email check.
45
1.3.34 (2015-07-08) Merge pull request #44 - Adding support to brazilian portuguese language.
56
1.3.33 (2015-07-02) Reset isolatedScope on route change

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.

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.35",
3+
"version": "1.3.36",
44
"author": "Ghislain B.",
55
"description": "Angular-Validation Directive and Service (ghiscoding)",
66
"main": "app.js",

protractor/mixed_validation_spec.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -440,14 +440,14 @@
440440

441441
it('Should show ValidationSummary and contain all error messages', function () {
442442
// showValidation checkbox should false at first but true after
443-
var elmCheckboxShowSummary = element(by.model('displayValidationSummary'));
443+
var elmCheckboxShowSummary = element(by.model('vm.displayValidationSummary'));
444444
expect(elmCheckboxShowSummary.isSelected()).toBeFalsy();
445445

446446
var btnShowSummary = $('[name=btn_showValidation]');
447447
btnShowSummary.click();
448448
browser.waitForAngular();
449449

450-
elmCheckboxShowSummary = element(by.model('displayValidationSummary'));
450+
elmCheckboxShowSummary = element(by.model('vm.displayValidationSummary'));
451451
expect(elmCheckboxShowSummary.isSelected()).toBeTruthy();
452452

453453
// scroll back to top
@@ -513,7 +513,7 @@
513513
browser.waitForAngular();
514514

515515
// showValidation checkbox should false at first but true after
516-
var elmCheckboxShowSummary = element(by.model('displayValidationSummary'));
516+
var elmCheckboxShowSummary = element(by.model('vm.displayValidationSummary'));
517517
expect(elmCheckboxShowSummary.isSelected()).toBeTruthy();
518518

519519
// scroll back to top

readme.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#Angular Validation (Directive / Service)
2-
`Version: 1.3.35`
2+
`Version: 1.3.36`
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!
@@ -85,6 +85,7 @@ All the documentation has been moved to the Wiki section, see the [github wiki](
8585
* Properties & Options
8686
* [Inputs (all local options)](https://github.com/ghiscoding/angular-validation/wiki/Inputs-(local-options))
8787
* [Global Options](https://github.com/ghiscoding/angular-validation/wiki/Global-Options)
88+
* [ControllerAs Syntax](https://github.com/ghiscoding/angular-validation/wiki/ControllerAs-Syntax)
8889
* Validators
8990
* [Available Validator Rules](https://github.com/ghiscoding/angular-validation/wiki/Available-Validators-(rules))
9091
* [Custom Regular Expression Pattern](https://github.com/ghiscoding/angular-validation/wiki/Regular-Expression-Pattern)

src/validation-common.js

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,12 @@ angular
2222
// watch on route change, then reset some global variables, so that we don't carry over other controller/view validations
2323
$rootScope.$on("$routeChangeStart", function (event, next, current) {
2424
if (!_bypassRootScopeReset) {
25-
_globalOptions.displayOnlyLastErrorMsg = false; // reset the option of displaying only the last error message
26-
_globalOptions.preValidateFormElements = false; // reset the option of pre-validate all form elements, false by default
27-
_globalOptions.isolatedScope = null; // reset used scope on route change
28-
_globalOptions.scope = null; // reset used scope on route change
29-
25+
_globalOptions = {
26+
displayOnlyLastErrorMsg: false, // reset the option of displaying only the last error message
27+
preValidateFormElements: false, // reset the option of pre-validate all form elements, false by default
28+
isolatedScope: null, // reset used scope on route change
29+
scope: null // reset used scope on route change
30+
};
3031
_formElements = []; // array containing all form elements, valid or invalid
3132
_validationSummary = []; // array containing the list of invalid fields inside a validationSummary
3233
}
@@ -65,6 +66,7 @@ angular
6566
validationCommon.prototype.defineValidation = defineValidation; // define our validation object
6667
validationCommon.prototype.getFormElementByName = getFormElementByName; // get the form element custom object by it's name
6768
validationCommon.prototype.getFormElements = getFormElements; // get the array of form elements (custom objects)
69+
validationCommon.prototype.getGlobalOptions = getGlobalOptions; // get the global options used by all validators (usually called by the validationService)
6870
validationCommon.prototype.isFieldRequired = isFieldRequired; // return boolean knowing if the current field is required
6971
validationCommon.prototype.initialize = initialize; // initialize current object with passed arguments
7072
validationCommon.prototype.mergeObjects = mergeObjects; // merge 2 javascript objects, Overwrites obj1's values with obj2's (basically Object2 as higher priority over Object1)
@@ -194,6 +196,14 @@ angular
194196
return _formElements;
195197
}
196198

199+
/** Get global options used by all validators
200+
* @param object attrs: global options
201+
* @return object self
202+
*/
203+
function getGlobalOptions() {
204+
return _globalOptions;
205+
}
206+
197207
/** Initialize the common object
198208
* @param object scope
199209
* @param object elm
@@ -263,13 +273,25 @@ angular
263273

264274
self.scope.$validationSummary = _validationSummary;
265275

266-
// and also save it inside the current scope form (if found)
276+
// overwrite the scope form (if found)
267277
if (!!form) {
268278
// since validationSummary contain errors of all forms
269279
// we need to find only the errors of current form and them into the current scope form object
270280
form.$validationSummary = arrayFindObjects(_validationSummary, 'formName', form.$name);
271281
}
272282

283+
// overwrite the ControllerAs alias if it was passed in the global options
284+
if (!!_globalOptions && !!_globalOptions.controllerAs) {
285+
_globalOptions.controllerAs.$validationSummary = _validationSummary;
286+
287+
// also overwrite it inside controllerAs form (if found)
288+
if (!!form) {
289+
var formName = form.$name.indexOf('.') >= 0 ? form.$name.split('.')[1] : form.$name;
290+
_globalOptions.controllerAs[formName].$validationSummary = arrayFindObjects(_validationSummary, 'formName', form.$name);
291+
}
292+
}
293+
294+
273295
return _validationSummary;
274296
}
275297

@@ -687,7 +709,7 @@ angular
687709
}
688710
}
689711

690-
// save validation summary scope root
712+
// save validation summary into scope root
691713
self.scope.$validationSummary = _validationSummary;
692714

693715
// and also save it inside the current scope form (if found)
@@ -697,6 +719,17 @@ angular
697719
form.$validationSummary = arrayFindObjects(_validationSummary, 'formName', form.$name);
698720
}
699721

722+
// also save it inside the ControllerAs alias if it was passed in the global options
723+
if (!!_globalOptions && !!_globalOptions.controllerAs) {
724+
_globalOptions.controllerAs.$validationSummary = _validationSummary;
725+
726+
// also save it inside controllerAs form (if found)
727+
if (!!form) {
728+
var formName = form.$name.indexOf('.') >= 0 ? form.$name.split('.')[1] : form.$name;
729+
_globalOptions.controllerAs[formName].$validationSummary = arrayFindObjects(_validationSummary, 'formName', form.$name);
730+
}
731+
}
732+
700733
return _validationSummary;
701734
}
702735

@@ -753,6 +786,22 @@ angular
753786
return -1;
754787
}
755788

789+
/** Explode a '.' dot notation string to an object
790+
* @param string str
791+
* @parem object
792+
* @return object
793+
*/
794+
function explodedDotNotationStringToObject(str, obj) {
795+
var split = str.split('.');
796+
797+
for (var k = 0, kln = split.length; k < kln; k++) {
798+
if(!!obj[split[k]]) {
799+
obj = obj[split[k]];
800+
}
801+
}
802+
return obj;
803+
}
804+
756805
/** Get the element's parent Angular form (if found)
757806
* @param object self
758807
* @return object scope form
@@ -764,19 +813,31 @@ angular
764813

765814
for (var i = 0; i < forms.length; i++) {
766815
var form = forms[i].form;
767-
if (!!form && form.name && self.scope[form.name]) {
768-
parentForm = self.scope[form.name];
769-
if (typeof parentForm.$name === "undefined") {
770-
parentForm.$name = form.name; // make sure it has a $name, since we use that variable later on
816+
817+
if (!!form && !!form.name) {
818+
parentForm = (!!_globalOptions && !!_globalOptions.controllerAs && form.name.indexOf('.') >= 0)
819+
? explodedDotNotationStringToObject(form.name, self.scope)
820+
: self.scope[form.name];
821+
822+
if(!!parentForm) {
823+
if (typeof parentForm.$name === "undefined") {
824+
parentForm.$name = form.name; // make sure it has a $name, since we use that variable later on
825+
}
826+
return parentForm;
771827
}
772-
return parentForm;
773828
}
774829
}
775830

776831
// falling here with a form name but without a form object found in the scope is often due to isolate scope
777832
// we can hack it and define our own form inside this isolate scope, in that way we can still use something like: isolateScope.form1.$validationSummary
778833
if (!!form && !!form.name) {
779-
return self.scope[form.name] = { $name: form.name, specialNote: 'Created by Angular-Validation for Isolated Scope usage' };
834+
var obj = { $name: form.name, specialNote: 'Created by Angular-Validation for Isolated Scope usage' };
835+
836+
if (!!_globalOptions && !!_globalOptions.controllerAs && form.name.indexOf('.') >= 0) {
837+
var formSplit = form.name.split('.');
838+
return self.scope[formSplit[0]][formSplit[1]] = obj
839+
}
840+
return self.scope[form.name] = obj;
780841
}
781842
return null;
782843
}

src/validation-directive.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171

7272
if (!formElmObj.isValidationCancelled) {
7373
// validate without delay
74-
attemptToValidate(event.target.value, 0);
74+
attemptToValidate(event.target.value, 10);
7575
}else {
7676
ctrl.$setValidity('validation', true);
7777
}

src/validation-service.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,16 @@ angular
1515
var _watchers = [];
1616

1717
// service constructor
18-
var validationService = function () {
18+
var validationService = function (globalOptions) {
1919
this.isValidationCancelled = false; // is the validation cancelled?
2020
this.timer = null; // timer of user inactivity time
2121
this.validationAttrs = {}; // Current Validator attributes
2222
this.commonObj = new validationCommon(); // Object of validationCommon service
23+
24+
// if global options were passed to the constructor
25+
if (!!globalOptions) {
26+
this.setGlobalOptions(globalOptions);
27+
}
2328
}
2429

2530
// list of available published public functions of this object
@@ -94,7 +99,7 @@ angular
9499
if (!formElmObj.isValidationCancelled) {
95100
// re-initialize to use current element & validate without delay
96101
self.commonObj.initialize(scope, attrs.elm, attrs, attrs.ctrl);
97-
attemptToValidate(self, event.target.value, 0);
102+
attemptToValidate(self, event.target.value, 10);
98103
}
99104
});
100105

@@ -138,7 +143,7 @@ angular
138143
var self = this;
139144
var ctrl, elm, elmName = '', isValid = true;
140145
if(typeof obj === "undefined" || typeof obj.$validationSummary === "undefined") {
141-
throw 'checkFormValidity() requires a valid Angular Form or $scope object passed as argument to work properly (ex.: $scope.form1 OR $scope).';
146+
throw 'checkFormValidity() requires a valid Angular Form or $scope/vm object passed as argument to work properly, for example:: fn($scope) OR fn($scope.form1) OR fn(vm) OR fn(vm.form1)';
142147
}
143148

144149
// loop through $validationSummary and display errors when found on each field
@@ -170,7 +175,7 @@ angular
170175
function clearInvalidValidatorsInSummary(obj) {
171176
var self = this;
172177
if (typeof obj === "undefined" || typeof obj.$validationSummary === "undefined") {
173-
throw 'clearInvalidValidatorsInSummary() requires a valid Angular Form or $scope object passed as argument to work properly (ex.: $scope.form1 OR $scope).';
178+
throw 'clearInvalidValidatorsInSummary() requires a valid Angular Form or $scope/vm object passed as argument to work properly, for example:: fn($scope) OR fn($scope.form1) OR fn(vm) OR fn(vm.form1)';
174179
}
175180
// Get list of names to remove
176181
var elmName = [];
@@ -196,7 +201,7 @@ angular
196201
var formElmObj;
197202

198203
if(typeof obj === "undefined" || typeof obj.$validationSummary === "undefined") {
199-
throw 'removeValidator() only works with Validation that were defined by the Service (not by the Directive) and requires a valid Angular Form or $scope object passed as argument to work properly (ex.: $scope.form1 OR $scope).';
204+
throw 'removeValidator() only works with Validation that were defined by the Service (not by the Directive) and requires a valid Angular Form or $scope/vm object passed as argument to work properly, for example:: fn($scope) OR fn($scope.form1) OR fn(vm) OR fn(vm.form1)';
200205
}
201206

202207
// Note: removeAttr() will remove validation attribute from the DOM (if defined by Directive), but as no effect when defined by the Service

0 commit comments

Comments
 (0)