├── .gitignore
├── CHANGELOG.md
├── Gruntfile.coffee
├── LICENSE
├── README.md
├── bower.json
├── karma.conf.js
├── package.json
├── src
├── showErrors.coffee
├── showErrors.js
└── showErrors.min.js
└── test
├── helpers.coffee
├── helpers.js
├── showErrors.spec.coffee
└── showErrors.spec.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | bower_components
3 | npm-debug.log
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ### 2.3.0
2 |
3 | * Bug Fixes
4 | * reverted the commit in v2.2.0 that no longer required inputs to have the form-control class. This broke select boxes.
5 |
6 | ### 2.2.0
7 |
8 | * Enhancements
9 | * Added option to skip the form group check. Thanks @lukaselmer
10 | * Allow input-group instead of form-group class. Thanks @morgenes
11 | * Works with inputs without the form-control class (helps it work with radio and checkbox controls). Thanks @Kheldar
12 |
13 | ### 2.1.0
14 |
15 | * Enhancements
16 | * Using `$interpolate` to retrieve the name of the input element. This allows the directive to work with interpolated form names. Thanks @cherrydev and @Templarian
17 |
18 | ### 2.0.0
19 |
20 | * Breaking Changes
21 | * Added a more specific selector query for the input element. The input element must now also have the 'form-control' class associated with it. Thanks @martindederer
22 |
23 | * Enhancements
24 | * Added `trigger` option to provide a custom trigger to validate the value. By default the trigger is the `blur` event. Thanks @Templarian
25 |
26 | ### 1.1.0
27 |
28 | * Enhancements
29 | * Added `showSuccess` option
30 |
31 | * Bug Fixes
32 | * Does not throw an undefined error when the form is dynamically created. Thanks @murphyalexandre
33 |
34 | ### 1.0.4
35 |
36 | * Bug Fixes
37 | * Using inline array notation to allow the js file to be minified
38 |
39 | ### 1.0.3
40 |
41 | * Bug Fixes
42 | * Fixed edge case where the error class was not removed correctly after manually checking validation.
43 |
44 | ### 1.0.2
45 |
46 | * refactorings
47 | * checking if name attribute exists in the link function instead of the compile function
48 |
--------------------------------------------------------------------------------
/Gruntfile.coffee:
--------------------------------------------------------------------------------
1 | module.exports = (grunt) ->
2 |
3 | grunt.initConfig
4 | coffee:
5 | options:
6 | bare: false
7 | compile:
8 | files:
9 | 'src/showErrors.js': 'src/showErrors.coffee'
10 | 'test/showErrors.spec.js': 'test/showErrors.spec.coffee'
11 | 'test/helpers.js': 'test/helpers.coffee'
12 | pkg: grunt.file.readJSON('package.json')
13 | uglify:
14 | options:
15 | banner: '/*! <%= pkg.name %> (version <%= pkg.version %>) <%= grunt.template.today("yyyy-mm-dd") %> */\n'
16 | build:
17 | src: 'src/showErrors.js'
18 | dest: 'src/showErrors.min.js'
19 | watch:
20 | files: [
21 | 'src/showErrors.coffee'
22 | 'test/showErrors.spec.coffee'
23 | ]
24 | tasks: 'default'
25 | karma:
26 | files: ['src/showErrors.js', 'test/showErrors.spec.js']
27 | tasks: ['karma:unit:run']
28 | karma:
29 | unit:
30 | configFile: 'karma.conf.js'
31 | singleRun: true
32 | continuous:
33 | configFile: 'karma.conf.js'
34 | background: true
35 |
36 | require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks)
37 |
38 | grunt.registerTask 'default', ['coffee', 'uglify', 'karma:unit']
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2013-2014 Paul Yoder
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Angular Bootstrap Show Errors
2 | =============================
3 |
4 | An Angular directive for Bootstrap 3 that intelligently applies the 'has-error' class to invalid form fields.
5 |
6 | See the [Bootstrap Form Validation Done Right in AngularJS](http://blog.yodersolutions.com/bootstrap-form-validation-done-right-in-angularjs?utm_source=github&utm_medium=readme&utm_campaign=code) blog post to read about the benefits of using this directive.
7 |
8 | Installation
9 | ---
10 | With Bower
11 |
12 | bower install angular-bootstrap-show-errors
13 |
14 | Manually
15 |
16 | Copy the `src/showErrors.js` or `src/showErrors.min.js` file into your project.
17 |
18 | Quick Start
19 | ---
20 | 1. Include the `ui.bootstrap.showErrors` module in your Angular app
21 | ```javascript
22 | angular.module('yourApp', ['ui.bootstrap.showErrors']);
23 | ```
24 |
25 | 2. Add the `show-errors` attribute on the div element that contains the `form-group` class
26 | ```html
27 |
32 | ```
33 |
34 | 3. If you want to avoid the extra bottom margin of `form-group`, you can use `input-group`.
35 | ```html
36 |
41 | ```
42 |
43 | Force Validity Check
44 | ---
45 | By default this directive doesn't check the validity until the user tabs off the input element. However, there are times you want to show invalid form elements even if the user has not tabbed off. (e.g. before saving the form)
46 |
47 | To force the validity check, broadcast the `show-errors-check-validity` event.
48 |
49 | #### Example
50 |
51 |
52 | ```html
53 |
59 | ```
60 |
61 | ```javascript
62 | $scope.save = function() {
63 | $scope.$broadcast('show-errors-check-validity');
64 |
65 | if ($scope.userForm.$valid) {
66 | // save the user
67 | }
68 | }
69 | ```
70 |
71 | Reset
72 | ---
73 | If you have functionality to reset your form, you can broadcast the 'show-errors-reset' event to remove any errors on the form elements.
74 |
75 | #### Example
76 |
77 | ```html
78 |
84 | ```
85 |
86 | ```javascript
87 | $scope.reset = function() {
88 | $scope.$broadcast('show-errors-reset');
89 | }
90 | ```
91 |
92 | Show Valid Entries
93 | ---
94 | It's also possible to let the user know when they have entered valid values by applying the 'show-success' class that Bootstrap provides.
95 | You can either apply this globally or on an element by element basis.
96 |
97 | ##### Globally
98 | The following example shows how to show valid values on every input that uses the showErrors directive.
99 |
100 | ```javascript
101 | app = angular.module('yourApp', ['ui.bootstrap.showErrors']);
102 | app.config(['showErrorsConfigProvider', function(showErrorsConfigProvider) {
103 | showErrorsConfigProvider.showSuccess(true);
104 | }]);
105 | ```
106 |
107 | ##### By Input Element
108 | If you only want to show valid values on specific inputs, then you can pass in the `{ showSuccess: true }` option like the example below shows.
109 |
110 | ```html
111 |
116 | ```
117 |
118 | Skip Form Group Check
119 | ---
120 | If your HTML code doesn't have a form-group class, the form group check can be skipped:
121 |
122 | ```html
123 |
128 | ```
129 |
130 | Custom Trigger
131 | ---
132 | By default, the validation is not performed until the `blur` event is trigger on the input
133 | element. However, there are some scenarios where this is not desirable, so it's possible to
134 | override this with the `trigger` option.
135 |
136 | ##### By Input Element
137 | ```html
138 |
143 | ```
144 |
145 | ##### Globally
146 | ```javascript
147 | app = angular.module('yourApp', ['ui.bootstrap.showErrors']);
148 | app.config(['showErrorsConfigProvider', function(showErrorsConfigProvider) {
149 | showErrorsConfigProvider.trigger('keypress');
150 | }]);
151 | ```
152 |
153 | ## Development
154 |
155 | ### Install Development Dependencies
156 | Before you begin development, you will need to install the required node modules and bower components. To do
157 | so, open a terminal window in the project directory and run the following commands.
158 | ```
159 | npm install
160 | bower install
161 | ```
162 |
163 | ### Compile and Run the Unit Tests
164 | Just type `grunt` in the command line to compile and run the karma unit tests once.
165 |
166 | If you want to have grunt watch for any file changes and automatically compile and run the karma
167 | unit tests, then run the following command:
168 | ```
169 | grunt karma:continuous:start watch
170 | ```
171 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-bootstrap-show-errors",
3 | "version": "2.3.0",
4 | "authors": [
5 | "Paul Yoder "
6 | ],
7 | "description": "An Angular directive for Bootstrap to intelligently show form validation errors",
8 | "main": "src/showErrors.js",
9 | "keywords": [
10 | "angular",
11 | "bootstrap",
12 | "directive",
13 | "validation"
14 | ],
15 | "license": "MIT",
16 | "homepage": "https://github.com/paulyoder/angular-bootstrap-show-errors",
17 | "ignore": [
18 | "**/.*",
19 | "node_modules",
20 | "bower_components",
21 | "test"
22 | ],
23 | "dependencies": {
24 | "angular": "*"
25 | },
26 | "devDependencies": {
27 | "angular": "1.2.0",
28 | "angular-mocks": "1.2.0"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | // Generated on Thu Oct 31 2013 11:47:14 GMT-0500 (Central Daylight Time)
3 |
4 | module.exports = function(config) {
5 | config.set({
6 |
7 | // base path, that will be used to resolve files and exclude
8 | basePath: '',
9 |
10 |
11 | // frameworks to use
12 | frameworks: ['jasmine'],
13 |
14 |
15 | // list of files / patterns to load in the browser
16 | files: [
17 | 'bower_components/angular/angular.js',
18 | 'bower_components/angular-mocks/angular-mocks.js',
19 | 'src/showErrors.js',
20 | 'test/helpers.js',
21 | 'test/showErrors.spec.js'
22 | ],
23 |
24 |
25 | // list of files to exclude
26 | exclude: [
27 |
28 | ],
29 |
30 |
31 | // test results reporter to use
32 | // possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
33 | reporters: ['progress'],
34 |
35 |
36 | // web server port
37 | port: 9876,
38 |
39 |
40 | // enable / disable colors in the output (reporters and logs)
41 | colors: true,
42 |
43 |
44 | // level of logging
45 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
46 | logLevel: config.LOG_INFO,
47 |
48 |
49 | // enable / disable watching file and executing tests whenever any file changes
50 | autoWatch: false,
51 |
52 |
53 | // Start these browsers, currently available:
54 | // - Chrome
55 | // - ChromeCanary
56 | // - Firefox
57 | // - Opera (has to be installed with `npm install karma-opera-launcher`)
58 | // - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)
59 | // - PhantomJS
60 | // - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)
61 | browsers: ['PhantomJS'],
62 |
63 |
64 | // If browser does not capture in given timeout [ms], kill it
65 | captureTimeout: 60000,
66 |
67 |
68 | // Continuous Integration mode
69 | // if true, it capture browsers, run tests and exit
70 | singleRun: false
71 | });
72 | };
73 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-bootstrap-show-errors",
3 | "version": "2.3.0",
4 | "description": "An Angular Directive to intelligently show form validation errors",
5 | "author": "Paul Yoder ",
6 | "license": "MIT",
7 | "homepage": "https://github.com/paulyoder/angular-bootstrap-show-errors",
8 | "main": "src/showErrors.js",
9 | "dependencies": {},
10 | "devDependencies": {
11 | "bower": "^1.3.9",
12 | "grunt": "0.4.1",
13 | "grunt-contrib-coffee": "~0.7.0",
14 | "grunt-contrib-uglify": "~0.2.5",
15 | "grunt-contrib-watch": "~0.5.3",
16 | "grunt-karma": "0.9.0",
17 | "matchdep": "0.3.0",
18 | "phantomjs": "~1.9.10",
19 | "karma-phantomjs-launcher": "~0.1.4",
20 | "karma-jasmine": "~0.1.5"
21 | },
22 | "scripts": {
23 | "test": "grunt --verbose"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/showErrors.coffee:
--------------------------------------------------------------------------------
1 | showErrorsModule = angular.module('ui.bootstrap.showErrors', [])
2 |
3 | showErrorsModule.directive 'showErrors',
4 | ['$timeout', 'showErrorsConfig', '$interpolate', ($timeout, showErrorsConfig, $interpolate) ->
5 |
6 | getTrigger = (options) ->
7 | trigger = showErrorsConfig.trigger
8 | if options && options.trigger?
9 | trigger = options.trigger
10 | trigger
11 |
12 | getShowSuccess = (options) ->
13 | showSuccess = showErrorsConfig.showSuccess
14 | if options && options.showSuccess?
15 | showSuccess = options.showSuccess
16 | showSuccess
17 |
18 | linkFn = (scope, el, attrs, formCtrl) ->
19 | blurred = false
20 | options = scope.$eval attrs.showErrors
21 | showSuccess = getShowSuccess options
22 | trigger = getTrigger options
23 |
24 | inputEl = el[0].querySelector '.form-control[name]'
25 | inputNgEl = angular.element inputEl
26 | inputName = $interpolate(inputNgEl.attr('name') || '')(scope)
27 | unless inputName
28 | throw "show-errors element has no child input elements with a 'name' attribute and a 'form-control' class"
29 |
30 | inputNgEl.bind trigger, ->
31 | blurred = true
32 | toggleClasses formCtrl[inputName].$invalid
33 |
34 | scope.$watch ->
35 | formCtrl[inputName] && formCtrl[inputName].$invalid
36 | , (invalid) ->
37 | return if !blurred
38 | toggleClasses invalid
39 |
40 | scope.$on 'show-errors-check-validity', ->
41 | toggleClasses formCtrl[inputName].$invalid
42 |
43 | scope.$on 'show-errors-reset', ->
44 | $timeout ->
45 | # want to run this after the current digest cycle
46 | el.removeClass 'has-error'
47 | el.removeClass 'has-success'
48 | blurred = false
49 | , 0, false
50 |
51 | toggleClasses = (invalid) ->
52 | el.toggleClass 'has-error', invalid
53 | if showSuccess
54 | el.toggleClass 'has-success', !invalid
55 |
56 | {
57 | restrict: 'A'
58 | require: '^form'
59 | compile: (elem, attrs) ->
60 | if attrs['showErrors'].indexOf('skipFormGroupCheck') == -1
61 | unless elem.hasClass('form-group') or elem.hasClass('input-group')
62 | throw "show-errors element does not have the 'form-group' or 'input-group' class"
63 | linkFn
64 | }
65 | ]
66 |
67 | showErrorsModule.provider 'showErrorsConfig', ->
68 | _showSuccess = false
69 | _trigger = 'blur'
70 |
71 | @showSuccess = (showSuccess) ->
72 | _showSuccess = showSuccess
73 |
74 | @trigger = (trigger) ->
75 | _trigger = trigger
76 |
77 | @$get = ->
78 | showSuccess: _showSuccess
79 | trigger: _trigger
80 |
81 | return
82 |
--------------------------------------------------------------------------------
/src/showErrors.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | var showErrorsModule;
3 |
4 | showErrorsModule = angular.module('ui.bootstrap.showErrors', []);
5 |
6 | showErrorsModule.directive('showErrors', [
7 | '$timeout', 'showErrorsConfig', '$interpolate', function($timeout, showErrorsConfig, $interpolate) {
8 | var getShowSuccess, getTrigger, linkFn;
9 | getTrigger = function(options) {
10 | var trigger;
11 | trigger = showErrorsConfig.trigger;
12 | if (options && (options.trigger != null)) {
13 | trigger = options.trigger;
14 | }
15 | return trigger;
16 | };
17 | getShowSuccess = function(options) {
18 | var showSuccess;
19 | showSuccess = showErrorsConfig.showSuccess;
20 | if (options && (options.showSuccess != null)) {
21 | showSuccess = options.showSuccess;
22 | }
23 | return showSuccess;
24 | };
25 | linkFn = function(scope, el, attrs, formCtrl) {
26 | var blurred, inputEl, inputName, inputNgEl, options, showSuccess, toggleClasses, trigger;
27 | blurred = false;
28 | options = scope.$eval(attrs.showErrors);
29 | showSuccess = getShowSuccess(options);
30 | trigger = getTrigger(options);
31 | inputEl = el[0].querySelector('.form-control[name]');
32 | inputNgEl = angular.element(inputEl);
33 | inputName = $interpolate(inputNgEl.attr('name') || '')(scope);
34 | if (!inputName) {
35 | throw "show-errors element has no child input elements with a 'name' attribute and a 'form-control' class";
36 | }
37 | inputNgEl.bind(trigger, function() {
38 | blurred = true;
39 | return toggleClasses(formCtrl[inputName].$invalid);
40 | });
41 | scope.$watch(function() {
42 | return formCtrl[inputName] && formCtrl[inputName].$invalid;
43 | }, function(invalid) {
44 | if (!blurred) {
45 | return;
46 | }
47 | return toggleClasses(invalid);
48 | });
49 | scope.$on('show-errors-check-validity', function() {
50 | return toggleClasses(formCtrl[inputName].$invalid);
51 | });
52 | scope.$on('show-errors-reset', function() {
53 | return $timeout(function() {
54 | el.removeClass('has-error');
55 | el.removeClass('has-success');
56 | return blurred = false;
57 | }, 0, false);
58 | });
59 | return toggleClasses = function(invalid) {
60 | el.toggleClass('has-error', invalid);
61 | if (showSuccess) {
62 | return el.toggleClass('has-success', !invalid);
63 | }
64 | };
65 | };
66 | return {
67 | restrict: 'A',
68 | require: '^form',
69 | compile: function(elem, attrs) {
70 | if (attrs['showErrors'].indexOf('skipFormGroupCheck') === -1) {
71 | if (!(elem.hasClass('form-group') || elem.hasClass('input-group'))) {
72 | throw "show-errors element does not have the 'form-group' or 'input-group' class";
73 | }
74 | }
75 | return linkFn;
76 | }
77 | };
78 | }
79 | ]);
80 |
81 | showErrorsModule.provider('showErrorsConfig', function() {
82 | var _showSuccess, _trigger;
83 | _showSuccess = false;
84 | _trigger = 'blur';
85 | this.showSuccess = function(showSuccess) {
86 | return _showSuccess = showSuccess;
87 | };
88 | this.trigger = function(trigger) {
89 | return _trigger = trigger;
90 | };
91 | this.$get = function() {
92 | return {
93 | showSuccess: _showSuccess,
94 | trigger: _trigger
95 | };
96 | };
97 | });
98 |
99 | }).call(this);
100 |
--------------------------------------------------------------------------------
/src/showErrors.min.js:
--------------------------------------------------------------------------------
1 | /*! angular-bootstrap-show-errors (version 2.3.0) 2015-01-19 */
2 | (function(){var a;a=angular.module("ui.bootstrap.showErrors",[]),a.directive("showErrors",["$timeout","showErrorsConfig","$interpolate",function(a,b,c){var d,e,f;return e=function(a){var c;return c=b.trigger,a&&null!=a.trigger&&(c=a.trigger),c},d=function(a){var c;return c=b.showSuccess,a&&null!=a.showSuccess&&(c=a.showSuccess),c},f=function(b,f,g,h){var i,j,k,l,m,n,o,p;if(i=!1,m=b.$eval(g.showErrors),n=d(m),p=e(m),j=f[0].querySelector(".form-control[name]"),l=angular.element(j),k=c(l.attr("name")||"")(b),!k)throw"show-errors element has no child input elements with a 'name' attribute and a 'form-control' class";return l.bind(p,function(){return i=!0,o(h[k].$invalid)}),b.$watch(function(){return h[k]&&h[k].$invalid},function(a){return i?o(a):void 0}),b.$on("show-errors-check-validity",function(){return o(h[k].$invalid)}),b.$on("show-errors-reset",function(){return a(function(){return f.removeClass("has-error"),f.removeClass("has-success"),i=!1},0,!1)}),o=function(a){return f.toggleClass("has-error",a),n?f.toggleClass("has-success",!a):void 0}},{restrict:"A",require:"^form",compile:function(a,b){if(-1===b.showErrors.indexOf("skipFormGroupCheck")&&!a.hasClass("form-group")&&!a.hasClass("input-group"))throw"show-errors element does not have the 'form-group' or 'input-group' class";return f}}}]),a.provider("showErrorsConfig",function(){var a,b;a=!1,b="blur",this.showSuccess=function(b){return a=b},this.trigger=function(a){return b=a},this.$get=function(){return{showSuccess:a,trigger:b}}})}).call(this);
--------------------------------------------------------------------------------
/test/helpers.coffee:
--------------------------------------------------------------------------------
1 | beforeEach ->
2 | @addMatchers
3 | toHaveClass: (klass) ->
4 | @message = ->
5 | "Expected '#{ angular.mock.dump(@actual) }' to have class '#{ klass }'."
6 |
7 | @actual.hasClass klass
8 |
--------------------------------------------------------------------------------
/test/helpers.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | beforeEach(function() {
3 | return this.addMatchers({
4 | toHaveClass: function(klass) {
5 | this.message = function() {
6 | return "Expected '" + (angular.mock.dump(this.actual)) + "' to have class '" + klass + "'.";
7 | };
8 | return this.actual.hasClass(klass);
9 | }
10 | });
11 | });
12 |
13 | }).call(this);
14 |
--------------------------------------------------------------------------------
/test/showErrors.spec.coffee:
--------------------------------------------------------------------------------
1 | describe 'showErrors', ->
2 | $compile = undefined
3 | $scope = undefined
4 | $timeout = undefined
5 | validName = 'Paul'
6 | invalidName = 'Pa'
7 |
8 | beforeEach module('ui.bootstrap.showErrors')
9 | beforeEach inject((_$compile_, _$rootScope_, _$timeout_) ->
10 | $compile = _$compile_
11 | $scope = _$rootScope_
12 | $timeout = _$timeout_
13 | )
14 |
15 | compileEl = ->
16 | el = $compile(
17 | ''
25 | )($scope)
26 | angular.element(document.body).append el
27 | $scope.$digest()
28 | el
29 |
30 | describe 'directive does not contain an input element with a form-control class and name attribute', ->
31 | it 'throws an exception', ->
32 | expect( ->
33 | $compile('')($scope)
34 | ).toThrow "show-errors element has no child input elements with a 'name' attribute and a 'form-control' class"
35 |
36 | it "throws an exception if the element doesn't have the form-group or input-group class", ->
37 | expect( ->
38 | $compile('')($scope)
39 | ).toThrow "show-errors element does not have the 'form-group' or 'input-group' class"
40 |
41 | it "doesn't throw an exception if the element has the input-group class", ->
42 | expect( ->
43 | $compile('')($scope)
44 | ).not.toThrow()
45 |
46 | it "doesn't throw an exception if the element doesn't have the form-group class but uses the skipFormGroupCheck option", ->
47 | expect( ->
48 | $compile('')($scope)
49 | ).not.toThrow()
50 |
51 | it "throws an exception if the element isn't in a form tag", ->
52 | expect( ->
53 | $compile('')($scope)
54 | ).toThrow()
55 |
56 | describe '$pristine && $invalid', ->
57 | it 'has-error is absent', ->
58 | el = compileEl()
59 | expectFormGroupHasErrorClass(el).toBe false
60 |
61 | describe '$dirty && $invalid && blurred', ->
62 | it 'has-error is present', ->
63 | el = compileEl()
64 | $scope.userForm.firstName.$setViewValue invalidName
65 | angular.element(firstNameEl(el)).triggerHandler 'blur'
66 | expectFormGroupHasErrorClass(el).toBe true
67 |
68 | describe '$dirty && $invalid && not blurred', ->
69 | it 'has-error is absent', ->
70 | el = compileEl()
71 | $scope.userForm.firstName.$setViewValue invalidName
72 | angular.element(firstNameEl(el)).triggerHandler 'keydown'
73 | expectFormGroupHasErrorClass(el).toBe false
74 |
75 | describe '$valid && blurred', ->
76 | it 'has-error is absent', ->
77 | el = compileEl()
78 | $scope.userForm.firstName.$setViewValue validName
79 | angular.element(firstNameEl(el)).triggerHandler 'blur'
80 | expectFormGroupHasErrorClass(el).toBe false
81 |
82 | describe '$valid && blurred then becomes $invalid before blurred', ->
83 | it 'has-error is present', ->
84 | el = compileEl()
85 | $scope.userForm.firstName.$setViewValue validName
86 | angular.element(firstNameEl(el)).triggerHandler 'blur'
87 | $scope.$apply ->
88 | $scope.userForm.firstName.$setViewValue invalidName
89 | expectFormGroupHasErrorClass(el).toBe true
90 |
91 | describe '$valid && blurred then becomes $valid before blurred', ->
92 | it 'has-error is absent', ->
93 | el = compileEl()
94 | $scope.userForm.firstName.$setViewValue validName
95 | angular.element(firstNameEl(el)).triggerHandler 'blur'
96 | $scope.$apply ->
97 | $scope.userForm.firstName.$setViewValue invalidName
98 | $scope.$apply ->
99 | $scope.userForm.firstName.$setViewValue validName
100 | expectFormGroupHasErrorClass(el).toBe false
101 |
102 | describe '$valid && blurred then becomes $invalid after blurred', ->
103 | it 'has-error is present', ->
104 | el = compileEl()
105 | $scope.userForm.firstName.$setViewValue validName
106 | angular.element(firstNameEl(el)).triggerHandler 'blur'
107 | $scope.userForm.firstName.$setViewValue invalidName
108 | angular.element(firstNameEl(el)).triggerHandler 'blur'
109 | expectFormGroupHasErrorClass(el).toBe true
110 |
111 | describe '$valid && blurred then $invalid after blurred then $valid after blurred', ->
112 | it 'has-error is absent', ->
113 | el = compileEl()
114 | $scope.userForm.firstName.$setViewValue validName
115 | angular.element(firstNameEl(el)).triggerHandler 'blur'
116 | $scope.userForm.firstName.$setViewValue invalidName
117 | angular.element(firstNameEl(el)).triggerHandler 'blur'
118 | $scope.userForm.firstName.$setViewValue validName
119 | angular.element(firstNameEl(el)).triggerHandler 'blur'
120 | expectFormGroupHasErrorClass(el).toBe false
121 |
122 | describe '$valid && other input is $invalid && blurred', ->
123 | it 'has-error is absent', ->
124 | el = compileEl()
125 | $scope.userForm.firstName.$setViewValue validName
126 | $scope.userForm.lastName.$setViewValue invalidName
127 | angular.element(firstNameEl(el)).triggerHandler 'blur'
128 | expectFormGroupHasErrorClass(el).toBe false
129 |
130 | describe '$invalid && showErrorsCheckValidity is set before blurred', ->
131 | it 'has-error is present', ->
132 | el = compileEl()
133 | $scope.userForm.firstName.$setViewValue invalidName
134 | $scope.$broadcast 'show-errors-check-validity'
135 | expectFormGroupHasErrorClass(el).toBe true
136 |
137 | describe 'showErrorsCheckValidity is called twice', ->
138 | it 'correctly applies the has-error class', ->
139 | el = compileEl()
140 | $scope.userForm.firstName.$setViewValue invalidName
141 | $scope.$broadcast 'show-errors-check-validity'
142 | $scope.userForm.firstName.$setViewValue validName
143 | angular.element(firstNameEl(el)).triggerHandler 'blur'
144 | $scope.userForm.firstName.$setViewValue invalidName
145 | $scope.$apply ->
146 | $scope.showErrorsCheckValidity = true
147 | expectFormGroupHasErrorClass(el).toBe true
148 |
149 | describe 'showErrorsReset', ->
150 | it 'removes has-error', ->
151 | el = compileEl()
152 | $scope.userForm.firstName.$setViewValue invalidName
153 | angular.element(firstNameEl(el)).triggerHandler 'blur'
154 | $scope.$broadcast 'show-errors-reset'
155 | $timeout.flush()
156 | expectFormGroupHasErrorClass(el).toBe false
157 |
158 | describe 'showErrorsReset then invalid without blurred', ->
159 | it 'has-error is absent', ->
160 | el = compileEl()
161 | $scope.userForm.firstName.$setViewValue validName
162 | angular.element(firstNameEl(el)).triggerHandler 'blur'
163 | $scope.$broadcast 'show-errors-reset'
164 | $timeout.flush()
165 | $scope.$apply ->
166 | $scope.userForm.firstName.$setViewValue invalidName
167 | expectFormGroupHasErrorClass(el).toBe false
168 |
169 | describe 'call showErrorsReset multiple times', ->
170 | it 'removes has-error', ->
171 | el = compileEl()
172 | $scope.userForm.firstName.$setViewValue invalidName
173 | angular.element(firstNameEl(el)).triggerHandler 'blur'
174 | $scope.$broadcast 'show-errors-reset'
175 | $timeout.flush()
176 | angular.element(firstNameEl(el)).triggerHandler 'blur'
177 | $scope.$broadcast 'show-errors-reset'
178 | $timeout.flush()
179 | expectFormGroupHasErrorClass(el).toBe false
180 |
181 | describe '{showSuccess: true} option', ->
182 | describe '$pristine && $valid', ->
183 | it 'has-success is absent', ->
184 | el = compileEl()
185 | expectLastNameFormGroupHasSuccessClass(el).toBe false
186 |
187 | describe '$dirty && $valid && blurred', ->
188 | it 'has-success is present', ->
189 | el = compileEl()
190 | $scope.userForm.lastName.$setViewValue validName
191 | angular.element(lastNameEl(el)).triggerHandler 'blur'
192 | $scope.$digest()
193 | expectLastNameFormGroupHasSuccessClass(el).toBe true
194 |
195 | describe '$dirty && $invalid && blurred', ->
196 | it 'has-success is present', ->
197 | el = compileEl()
198 | $scope.userForm.lastName.$setViewValue invalidName
199 | angular.element(lastNameEl(el)).triggerHandler 'blur'
200 | $scope.$digest()
201 | expectLastNameFormGroupHasSuccessClass(el).toBe false
202 |
203 | describe '$invalid && blurred then becomes $valid before blurred', ->
204 | it 'has-success is present', ->
205 | el = compileEl()
206 | $scope.userForm.lastName.$setViewValue invalidName
207 | angular.element(lastNameEl(el)).triggerHandler 'blur'
208 | $scope.$apply ->
209 | $scope.userForm.lastName.$setViewValue invalidName
210 | $scope.$apply ->
211 | $scope.userForm.lastName.$setViewValue validName
212 | expectLastNameFormGroupHasSuccessClass(el).toBe true
213 |
214 | describe '$valid && showErrorsCheckValidity is set before blurred', ->
215 | it 'has-success is present', ->
216 | el = compileEl()
217 | $scope.userForm.lastName.$setViewValue validName
218 | $scope.$broadcast 'show-errors-check-validity'
219 | expectLastNameFormGroupHasSuccessClass(el).toBe true
220 |
221 | describe 'showErrorsReset', ->
222 | it 'removes has-success', ->
223 | el = compileEl()
224 | $scope.userForm.lastName.$setViewValue validName
225 | angular.element(lastNameEl(el)).triggerHandler 'blur'
226 | $scope.$broadcast 'show-errors-reset'
227 | $timeout.flush()
228 | expectLastNameFormGroupHasSuccessClass(el).toBe false
229 |
230 | describe 'showErrorsConfig', ->
231 | $compile = undefined
232 | $scope = undefined
233 | $timeout = undefined
234 | validName = 'Paul'
235 | invalidName = 'Pa'
236 |
237 | beforeEach ->
238 | testModule = angular.module 'testModule', []
239 | testModule.config (showErrorsConfigProvider) ->
240 | showErrorsConfigProvider.showSuccess true
241 | showErrorsConfigProvider.trigger 'keypress'
242 |
243 | module 'ui.bootstrap.showErrors', 'testModule'
244 |
245 | inject((_$compile_, _$rootScope_, _$timeout_) ->
246 | $compile = _$compile_
247 | $scope = _$rootScope_
248 | $timeout = _$timeout_
249 | )
250 |
251 | compileEl = ->
252 | el = $compile(
253 | ''
261 | )($scope)
262 | angular.element(document.body).append el
263 | $scope.$digest()
264 | el
265 |
266 | describe 'when showErrorsConfig.showSuccess is true', ->
267 | describe 'and no options given', ->
268 | it 'show-success class is applied', ->
269 | el = compileEl()
270 | $scope.userForm.lastName.$setViewValue validName
271 | angular.element(lastNameEl(el)).triggerHandler 'keypress'
272 | $scope.$digest()
273 | expectLastNameFormGroupHasSuccessClass(el).toBe true
274 |
275 | describe 'when showErrorsConfig.showSuccess is true', ->
276 | describe 'but options.showSuccess is false', ->
277 | it 'show-success class is not applied', ->
278 | el = compileEl()
279 | $scope.userForm.firstName.$setViewValue validName
280 | angular.element(firstNameEl(el)).triggerHandler 'blur'
281 | $scope.$digest()
282 | expectFirstNameFormGroupHasSuccessClass(el).toBe false
283 |
284 | describe 'when showErrorsConfig.trigger is "keypress"', ->
285 | describe 'and no options given', ->
286 | it 'validates the value on the first keypress', ->
287 | el = compileEl()
288 | $scope.userForm.lastName.$setViewValue invalidName
289 | angular.element(lastNameEl(el)).triggerHandler 'keypress'
290 | $scope.$digest()
291 | expectLastNameFormGroupHasErrorClass(el).toBe true
292 |
293 | describe 'but options.trigger is "blur"', ->
294 | it 'does not validate the value on keypress', ->
295 | el = compileEl()
296 | $scope.userForm.firstName.$setViewValue invalidName
297 | angular.element(firstNameEl(el)).triggerHandler 'keypress'
298 | $scope.$digest()
299 | expectFirstNameFormGroupHasErrorClass(el).toBe false
300 |
301 | find = (el, selector) ->
302 | el[0].querySelector selector
303 |
304 | firstNameEl = (el) ->
305 | find el, '[name=firstName]'
306 |
307 | lastNameEl = (el) ->
308 | find el, '[name=lastName]'
309 |
310 | expectFormGroupHasErrorClass = (el) ->
311 | formGroup = el[0].querySelector '[id=first-name-group]'
312 | expect angular.element(formGroup).hasClass('has-error')
313 |
314 | expectFirstNameFormGroupHasSuccessClass = (el) ->
315 | formGroup = el[0].querySelector '[id=first-name-group]'
316 | expect angular.element(formGroup).hasClass('has-success')
317 |
318 | expectLastNameFormGroupHasSuccessClass = (el) ->
319 | formGroup = el[0].querySelector '[id=last-name-group]'
320 | expect angular.element(formGroup).hasClass('has-success')
321 |
322 | expectFirstNameFormGroupHasErrorClass = (el) ->
323 | formGroup = el[0].querySelector '[id=first-name-group]'
324 | expect angular.element(formGroup).hasClass('has-error')
325 |
326 | expectLastNameFormGroupHasErrorClass = (el) ->
327 | formGroup = el[0].querySelector '[id=last-name-group]'
328 | expect angular.element(formGroup).hasClass('has-error')
329 |
--------------------------------------------------------------------------------
/test/showErrors.spec.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | var expectFirstNameFormGroupHasErrorClass, expectFirstNameFormGroupHasSuccessClass, expectFormGroupHasErrorClass, expectLastNameFormGroupHasErrorClass, expectLastNameFormGroupHasSuccessClass, find, firstNameEl, lastNameEl;
3 |
4 | describe('showErrors', function() {
5 | var $compile, $scope, $timeout, compileEl, invalidName, validName;
6 | $compile = void 0;
7 | $scope = void 0;
8 | $timeout = void 0;
9 | validName = 'Paul';
10 | invalidName = 'Pa';
11 | beforeEach(module('ui.bootstrap.showErrors'));
12 | beforeEach(inject(function(_$compile_, _$rootScope_, _$timeout_) {
13 | $compile = _$compile_;
14 | $scope = _$rootScope_;
15 | return $timeout = _$timeout_;
16 | }));
17 | compileEl = function() {
18 | var el;
19 | el = $compile('')($scope);
27 | angular.element(document.body).append(el);
28 | $scope.$digest();
29 | return el;
30 | };
31 | describe('directive does not contain an input element with a form-control class and name attribute', function() {
32 | return it('throws an exception', function() {
33 | return expect(function() {
34 | return $compile('')($scope);
35 | }).toThrow("show-errors element has no child input elements with a 'name' attribute and a 'form-control' class");
36 | });
37 | });
38 | it("throws an exception if the element doesn't have the form-group or input-group class", function() {
39 | return expect(function() {
40 | return $compile('')($scope);
41 | }).toThrow("show-errors element does not have the 'form-group' or 'input-group' class");
42 | });
43 | it("doesn't throw an exception if the element has the input-group class", function() {
44 | return expect(function() {
45 | return $compile('')($scope);
46 | }).not.toThrow();
47 | });
48 | it("doesn't throw an exception if the element doesn't have the form-group class but uses the skipFormGroupCheck option", function() {
49 | return expect(function() {
50 | return $compile('')($scope);
51 | }).not.toThrow();
52 | });
53 | it("throws an exception if the element isn't in a form tag", function() {
54 | return expect(function() {
55 | return $compile('')($scope);
56 | }).toThrow();
57 | });
58 | describe('$pristine && $invalid', function() {
59 | return it('has-error is absent', function() {
60 | var el;
61 | el = compileEl();
62 | return expectFormGroupHasErrorClass(el).toBe(false);
63 | });
64 | });
65 | describe('$dirty && $invalid && blurred', function() {
66 | return it('has-error is present', function() {
67 | var el;
68 | el = compileEl();
69 | $scope.userForm.firstName.$setViewValue(invalidName);
70 | angular.element(firstNameEl(el)).triggerHandler('blur');
71 | return expectFormGroupHasErrorClass(el).toBe(true);
72 | });
73 | });
74 | describe('$dirty && $invalid && not blurred', function() {
75 | return it('has-error is absent', function() {
76 | var el;
77 | el = compileEl();
78 | $scope.userForm.firstName.$setViewValue(invalidName);
79 | angular.element(firstNameEl(el)).triggerHandler('keydown');
80 | return expectFormGroupHasErrorClass(el).toBe(false);
81 | });
82 | });
83 | describe('$valid && blurred', function() {
84 | return it('has-error is absent', function() {
85 | var el;
86 | el = compileEl();
87 | $scope.userForm.firstName.$setViewValue(validName);
88 | angular.element(firstNameEl(el)).triggerHandler('blur');
89 | return expectFormGroupHasErrorClass(el).toBe(false);
90 | });
91 | });
92 | describe('$valid && blurred then becomes $invalid before blurred', function() {
93 | return it('has-error is present', function() {
94 | var el;
95 | el = compileEl();
96 | $scope.userForm.firstName.$setViewValue(validName);
97 | angular.element(firstNameEl(el)).triggerHandler('blur');
98 | $scope.$apply(function() {
99 | return $scope.userForm.firstName.$setViewValue(invalidName);
100 | });
101 | return expectFormGroupHasErrorClass(el).toBe(true);
102 | });
103 | });
104 | describe('$valid && blurred then becomes $valid before blurred', function() {
105 | return it('has-error is absent', function() {
106 | var el;
107 | el = compileEl();
108 | $scope.userForm.firstName.$setViewValue(validName);
109 | angular.element(firstNameEl(el)).triggerHandler('blur');
110 | $scope.$apply(function() {
111 | return $scope.userForm.firstName.$setViewValue(invalidName);
112 | });
113 | $scope.$apply(function() {
114 | return $scope.userForm.firstName.$setViewValue(validName);
115 | });
116 | return expectFormGroupHasErrorClass(el).toBe(false);
117 | });
118 | });
119 | describe('$valid && blurred then becomes $invalid after blurred', function() {
120 | return it('has-error is present', function() {
121 | var el;
122 | el = compileEl();
123 | $scope.userForm.firstName.$setViewValue(validName);
124 | angular.element(firstNameEl(el)).triggerHandler('blur');
125 | $scope.userForm.firstName.$setViewValue(invalidName);
126 | angular.element(firstNameEl(el)).triggerHandler('blur');
127 | return expectFormGroupHasErrorClass(el).toBe(true);
128 | });
129 | });
130 | describe('$valid && blurred then $invalid after blurred then $valid after blurred', function() {
131 | return it('has-error is absent', function() {
132 | var el;
133 | el = compileEl();
134 | $scope.userForm.firstName.$setViewValue(validName);
135 | angular.element(firstNameEl(el)).triggerHandler('blur');
136 | $scope.userForm.firstName.$setViewValue(invalidName);
137 | angular.element(firstNameEl(el)).triggerHandler('blur');
138 | $scope.userForm.firstName.$setViewValue(validName);
139 | angular.element(firstNameEl(el)).triggerHandler('blur');
140 | return expectFormGroupHasErrorClass(el).toBe(false);
141 | });
142 | });
143 | describe('$valid && other input is $invalid && blurred', function() {
144 | return it('has-error is absent', function() {
145 | var el;
146 | el = compileEl();
147 | $scope.userForm.firstName.$setViewValue(validName);
148 | $scope.userForm.lastName.$setViewValue(invalidName);
149 | angular.element(firstNameEl(el)).triggerHandler('blur');
150 | return expectFormGroupHasErrorClass(el).toBe(false);
151 | });
152 | });
153 | describe('$invalid && showErrorsCheckValidity is set before blurred', function() {
154 | return it('has-error is present', function() {
155 | var el;
156 | el = compileEl();
157 | $scope.userForm.firstName.$setViewValue(invalidName);
158 | $scope.$broadcast('show-errors-check-validity');
159 | return expectFormGroupHasErrorClass(el).toBe(true);
160 | });
161 | });
162 | describe('showErrorsCheckValidity is called twice', function() {
163 | return it('correctly applies the has-error class', function() {
164 | var el;
165 | el = compileEl();
166 | $scope.userForm.firstName.$setViewValue(invalidName);
167 | $scope.$broadcast('show-errors-check-validity');
168 | $scope.userForm.firstName.$setViewValue(validName);
169 | angular.element(firstNameEl(el)).triggerHandler('blur');
170 | $scope.userForm.firstName.$setViewValue(invalidName);
171 | $scope.$apply(function() {
172 | return $scope.showErrorsCheckValidity = true;
173 | });
174 | return expectFormGroupHasErrorClass(el).toBe(true);
175 | });
176 | });
177 | describe('showErrorsReset', function() {
178 | return it('removes has-error', function() {
179 | var el;
180 | el = compileEl();
181 | $scope.userForm.firstName.$setViewValue(invalidName);
182 | angular.element(firstNameEl(el)).triggerHandler('blur');
183 | $scope.$broadcast('show-errors-reset');
184 | $timeout.flush();
185 | return expectFormGroupHasErrorClass(el).toBe(false);
186 | });
187 | });
188 | describe('showErrorsReset then invalid without blurred', function() {
189 | return it('has-error is absent', function() {
190 | var el;
191 | el = compileEl();
192 | $scope.userForm.firstName.$setViewValue(validName);
193 | angular.element(firstNameEl(el)).triggerHandler('blur');
194 | $scope.$broadcast('show-errors-reset');
195 | $timeout.flush();
196 | $scope.$apply(function() {
197 | return $scope.userForm.firstName.$setViewValue(invalidName);
198 | });
199 | return expectFormGroupHasErrorClass(el).toBe(false);
200 | });
201 | });
202 | describe('call showErrorsReset multiple times', function() {
203 | return it('removes has-error', function() {
204 | var el;
205 | el = compileEl();
206 | $scope.userForm.firstName.$setViewValue(invalidName);
207 | angular.element(firstNameEl(el)).triggerHandler('blur');
208 | $scope.$broadcast('show-errors-reset');
209 | $timeout.flush();
210 | angular.element(firstNameEl(el)).triggerHandler('blur');
211 | $scope.$broadcast('show-errors-reset');
212 | $timeout.flush();
213 | return expectFormGroupHasErrorClass(el).toBe(false);
214 | });
215 | });
216 | return describe('{showSuccess: true} option', function() {
217 | describe('$pristine && $valid', function() {
218 | return it('has-success is absent', function() {
219 | var el;
220 | el = compileEl();
221 | return expectLastNameFormGroupHasSuccessClass(el).toBe(false);
222 | });
223 | });
224 | describe('$dirty && $valid && blurred', function() {
225 | return it('has-success is present', function() {
226 | var el;
227 | el = compileEl();
228 | $scope.userForm.lastName.$setViewValue(validName);
229 | angular.element(lastNameEl(el)).triggerHandler('blur');
230 | $scope.$digest();
231 | return expectLastNameFormGroupHasSuccessClass(el).toBe(true);
232 | });
233 | });
234 | describe('$dirty && $invalid && blurred', function() {
235 | return it('has-success is present', function() {
236 | var el;
237 | el = compileEl();
238 | $scope.userForm.lastName.$setViewValue(invalidName);
239 | angular.element(lastNameEl(el)).triggerHandler('blur');
240 | $scope.$digest();
241 | return expectLastNameFormGroupHasSuccessClass(el).toBe(false);
242 | });
243 | });
244 | describe('$invalid && blurred then becomes $valid before blurred', function() {
245 | return it('has-success is present', function() {
246 | var el;
247 | el = compileEl();
248 | $scope.userForm.lastName.$setViewValue(invalidName);
249 | angular.element(lastNameEl(el)).triggerHandler('blur');
250 | $scope.$apply(function() {
251 | return $scope.userForm.lastName.$setViewValue(invalidName);
252 | });
253 | $scope.$apply(function() {
254 | return $scope.userForm.lastName.$setViewValue(validName);
255 | });
256 | return expectLastNameFormGroupHasSuccessClass(el).toBe(true);
257 | });
258 | });
259 | describe('$valid && showErrorsCheckValidity is set before blurred', function() {
260 | return it('has-success is present', function() {
261 | var el;
262 | el = compileEl();
263 | $scope.userForm.lastName.$setViewValue(validName);
264 | $scope.$broadcast('show-errors-check-validity');
265 | return expectLastNameFormGroupHasSuccessClass(el).toBe(true);
266 | });
267 | });
268 | return describe('showErrorsReset', function() {
269 | return it('removes has-success', function() {
270 | var el;
271 | el = compileEl();
272 | $scope.userForm.lastName.$setViewValue(validName);
273 | angular.element(lastNameEl(el)).triggerHandler('blur');
274 | $scope.$broadcast('show-errors-reset');
275 | $timeout.flush();
276 | return expectLastNameFormGroupHasSuccessClass(el).toBe(false);
277 | });
278 | });
279 | });
280 | });
281 |
282 | describe('showErrorsConfig', function() {
283 | var $compile, $scope, $timeout, compileEl, invalidName, validName;
284 | $compile = void 0;
285 | $scope = void 0;
286 | $timeout = void 0;
287 | validName = 'Paul';
288 | invalidName = 'Pa';
289 | beforeEach(function() {
290 | var testModule;
291 | testModule = angular.module('testModule', []);
292 | testModule.config(function(showErrorsConfigProvider) {
293 | showErrorsConfigProvider.showSuccess(true);
294 | return showErrorsConfigProvider.trigger('keypress');
295 | });
296 | module('ui.bootstrap.showErrors', 'testModule');
297 | return inject(function(_$compile_, _$rootScope_, _$timeout_) {
298 | $compile = _$compile_;
299 | $scope = _$rootScope_;
300 | return $timeout = _$timeout_;
301 | });
302 | });
303 | compileEl = function() {
304 | var el;
305 | el = $compile('')($scope);
313 | angular.element(document.body).append(el);
314 | $scope.$digest();
315 | return el;
316 | };
317 | describe('when showErrorsConfig.showSuccess is true', function() {
318 | return describe('and no options given', function() {
319 | return it('show-success class is applied', function() {
320 | var el;
321 | el = compileEl();
322 | $scope.userForm.lastName.$setViewValue(validName);
323 | angular.element(lastNameEl(el)).triggerHandler('keypress');
324 | $scope.$digest();
325 | return expectLastNameFormGroupHasSuccessClass(el).toBe(true);
326 | });
327 | });
328 | });
329 | describe('when showErrorsConfig.showSuccess is true', function() {
330 | return describe('but options.showSuccess is false', function() {
331 | return it('show-success class is not applied', function() {
332 | var el;
333 | el = compileEl();
334 | $scope.userForm.firstName.$setViewValue(validName);
335 | angular.element(firstNameEl(el)).triggerHandler('blur');
336 | $scope.$digest();
337 | return expectFirstNameFormGroupHasSuccessClass(el).toBe(false);
338 | });
339 | });
340 | });
341 | return describe('when showErrorsConfig.trigger is "keypress"', function() {
342 | describe('and no options given', function() {
343 | return it('validates the value on the first keypress', function() {
344 | var el;
345 | el = compileEl();
346 | $scope.userForm.lastName.$setViewValue(invalidName);
347 | angular.element(lastNameEl(el)).triggerHandler('keypress');
348 | $scope.$digest();
349 | return expectLastNameFormGroupHasErrorClass(el).toBe(true);
350 | });
351 | });
352 | return describe('but options.trigger is "blur"', function() {
353 | return it('does not validate the value on keypress', function() {
354 | var el;
355 | el = compileEl();
356 | $scope.userForm.firstName.$setViewValue(invalidName);
357 | angular.element(firstNameEl(el)).triggerHandler('keypress');
358 | $scope.$digest();
359 | return expectFirstNameFormGroupHasErrorClass(el).toBe(false);
360 | });
361 | });
362 | });
363 | });
364 |
365 | find = function(el, selector) {
366 | return el[0].querySelector(selector);
367 | };
368 |
369 | firstNameEl = function(el) {
370 | return find(el, '[name=firstName]');
371 | };
372 |
373 | lastNameEl = function(el) {
374 | return find(el, '[name=lastName]');
375 | };
376 |
377 | expectFormGroupHasErrorClass = function(el) {
378 | var formGroup;
379 | formGroup = el[0].querySelector('[id=first-name-group]');
380 | return expect(angular.element(formGroup).hasClass('has-error'));
381 | };
382 |
383 | expectFirstNameFormGroupHasSuccessClass = function(el) {
384 | var formGroup;
385 | formGroup = el[0].querySelector('[id=first-name-group]');
386 | return expect(angular.element(formGroup).hasClass('has-success'));
387 | };
388 |
389 | expectLastNameFormGroupHasSuccessClass = function(el) {
390 | var formGroup;
391 | formGroup = el[0].querySelector('[id=last-name-group]');
392 | return expect(angular.element(formGroup).hasClass('has-success'));
393 | };
394 |
395 | expectFirstNameFormGroupHasErrorClass = function(el) {
396 | var formGroup;
397 | formGroup = el[0].querySelector('[id=first-name-group]');
398 | return expect(angular.element(formGroup).hasClass('has-error'));
399 | };
400 |
401 | expectLastNameFormGroupHasErrorClass = function(el) {
402 | var formGroup;
403 | formGroup = el[0].querySelector('[id=last-name-group]');
404 | return expect(angular.element(formGroup).hasClass('has-error'));
405 | };
406 |
407 | }).call(this);
408 |
--------------------------------------------------------------------------------