From da9263adbff7384e9c5cf99dc4d9e91e807ba875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Andr=C3=A9s=20Gallinal?= Date: Mon, 30 Dec 2013 11:52:25 -0300 Subject: [PATCH 1/2] 1st form. implementation --- src/ng/directive/form.js | 20 ++++++++++++++++++-- src/ng/directive/input.js | 6 ++++-- src/ng/directive/ngEventDirs.js | 19 ++++++++++++++++++- test/ng/directive/formSpec.js | 24 ++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/ng/directive/form.js b/src/ng/directive/form.js index 0cd70844ee72..9f3f92ab86ac 100644 --- a/src/ng/directive/form.js +++ b/src/ng/directive/form.js @@ -6,7 +6,8 @@ var nullFormCtrl = { $removeControl: noop, $setValidity: noop, $setDirty: noop, - $setPristine: noop + $setPristine: noop, + $setAttempted: noop }; /** @@ -60,6 +61,7 @@ function FormController(element, attrs) { form.$pristine = true; form.$valid = true; form.$invalid = false; + form.$attempted = false; parentForm.$addControl(form); @@ -206,9 +208,22 @@ function FormController(element, attrs) { control.$setPristine(); }); }; + + /** + * @ngdoc function + * @name ng.directive:form.FormController#$setAttempted + * @methodOf ng.directive:form.FormController + * + * @description + * Sets the form to its submission attempted state. + */ + form.$setAttempted = function (value) { + value ? element.addClass(ATTEMPTED_CLASS) : element.removeClass(ATTEMPTED_CLASS); + form.$attempted = value; + parentForm.$setAttempted(value); + }; } - /** * @ngdoc directive * @name ng.directive:ngForm @@ -253,6 +268,7 @@ function FormController(element, attrs) { * - `ng-invalid` Is set if the form is invalid. * - `ng-pristine` Is set if the form is pristine. * - `ng-dirty` Is set if the form is dirty. + * - `ng-attempted` Is set if the form was submitted in invalid state. * * * # Submitting a form and preventing the default action diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 6a974d9dae02..b42a8375eb54 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -5,7 +5,8 @@ -VALID_CLASS, -INVALID_CLASS, -PRISTINE_CLASS, - -DIRTY_CLASS + -DIRTY_CLASS, + -ATTEMPTED_CLASS */ var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/; @@ -828,7 +829,8 @@ var inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) { var VALID_CLASS = 'ng-valid', INVALID_CLASS = 'ng-invalid', PRISTINE_CLASS = 'ng-pristine', - DIRTY_CLASS = 'ng-dirty'; + DIRTY_CLASS = 'ng-dirty', + ATTEMPTED_CLASS = 'ng-attempted'; /** * @ngdoc object diff --git a/src/ng/directive/ngEventDirs.js b/src/ng/directive/ngEventDirs.js index e45f5cb71d98..7b76d2a25d96 100644 --- a/src/ng/directive/ngEventDirs.js +++ b/src/ng/directive/ngEventDirs.js @@ -37,7 +37,7 @@ */ var ngEventDirectives = {}; forEach( - 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '), + 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress focus blur copy cut paste'.split(' '), function(name) { var directiveName = directiveNormalize('ng-' + name); ngEventDirectives[directiveName] = ['$parse', function($parse) { @@ -333,6 +333,23 @@ forEach( */ + ngEventDirectives['ngSubmit'] = ['$parse', function($parse) { + return { + require: '^form', + compile: function($element, attr) { + var fn = $parse(attr['ngSubmit']); + return function(scope, element, attr, ctrl) { + element.on('submit', function(event) { + scope.$apply(function() { + ctrl.$setAttempted(ctrl.$invalid); + fn(scope, {$event:event}); + }); + }); + }; + } + }; + }]; + /** * @ngdoc directive * @name ng.directive:ngFocus diff --git a/test/ng/directive/formSpec.js b/test/ng/directive/formSpec.js index dde6f0a026c8..fd94aa5e5a19 100644 --- a/test/ng/directive/formSpec.js +++ b/test/ng/directive/formSpec.js @@ -316,6 +316,9 @@ describe('form', function() { child.$setDirty(); expect(parent.$dirty).toBeTruthy(); + + child.$setAttempted(true); + expect(parent.$attempted).toBeTruthy(); }); @@ -593,4 +596,25 @@ describe('form', function() { expect(nestedInputCtrl.$dirty).toBe(false); }); }); + + describe('$setAttempted', function() { + beforeEach(function() { + doc = $compile( + '
' + + '' + + '' + + '
')(scope); + + scope.$digest(); + }); + + it('should not init in attempted state', function() { + expect(scope.form.$attempted).toBe(false); + }); + + it('should be in attempted state when invalid and submitted', function() { + browserTrigger(doc, 'submit'); + expect(scope.form.$attempted).toBe(true); + }); + }); }); From d77214e4988c1918b95ed334d5a31a83fc3b79bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Andr=C3=A9s=20Gallinal?= Date: Mon, 30 Dec 2013 13:42:05 -0300 Subject: [PATCH 2/2] feat(form): $attempted state Added new state to form: - it sets to true when form submitted having $invalid state - it sets back to false when form submitted having valid state --- src/ng/directive/form.js | 14 ++++++++++++-- src/ng/directive/input.js | 6 ++---- src/ng/directive/ngEventDirs.js | 19 +------------------ 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/src/ng/directive/form.js b/src/ng/directive/form.js index 9f3f92ab86ac..cf02ac5cb6ac 100644 --- a/src/ng/directive/form.js +++ b/src/ng/directive/form.js @@ -1,6 +1,9 @@ 'use strict'; -/* global -nullFormCtrl */ +/* global + -nullFormCtrl, + -ATTEMPTED_CLASS +*/ var nullFormCtrl = { $addControl: noop, $removeControl: noop, @@ -8,7 +11,8 @@ var nullFormCtrl = { $setDirty: noop, $setPristine: noop, $setAttempted: noop -}; +}, +ATTEMPTED_CLASS = 'ng-attempted'; /** * @ngdoc object @@ -366,6 +370,12 @@ var formDirectiveFactory = function(isNgForm) { removeEventListenerFn(formElement[0], 'submit', preventDefaultListener); }, 0, false); }); + + formElement.on('submit', function() { + scope.$apply(function() { + controller.$setAttempted(controller.$invalid); + }); + }); } var parentFormCtrl = formElement.parent().controller('form'), diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index b42a8375eb54..6a974d9dae02 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -5,8 +5,7 @@ -VALID_CLASS, -INVALID_CLASS, -PRISTINE_CLASS, - -DIRTY_CLASS, - -ATTEMPTED_CLASS + -DIRTY_CLASS */ var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/; @@ -829,8 +828,7 @@ var inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) { var VALID_CLASS = 'ng-valid', INVALID_CLASS = 'ng-invalid', PRISTINE_CLASS = 'ng-pristine', - DIRTY_CLASS = 'ng-dirty', - ATTEMPTED_CLASS = 'ng-attempted'; + DIRTY_CLASS = 'ng-dirty'; /** * @ngdoc object diff --git a/src/ng/directive/ngEventDirs.js b/src/ng/directive/ngEventDirs.js index 7b76d2a25d96..e45f5cb71d98 100644 --- a/src/ng/directive/ngEventDirs.js +++ b/src/ng/directive/ngEventDirs.js @@ -37,7 +37,7 @@ */ var ngEventDirectives = {}; forEach( - 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress focus blur copy cut paste'.split(' '), + 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '), function(name) { var directiveName = directiveNormalize('ng-' + name); ngEventDirectives[directiveName] = ['$parse', function($parse) { @@ -333,23 +333,6 @@ forEach( */ - ngEventDirectives['ngSubmit'] = ['$parse', function($parse) { - return { - require: '^form', - compile: function($element, attr) { - var fn = $parse(attr['ngSubmit']); - return function(scope, element, attr, ctrl) { - element.on('submit', function(event) { - scope.$apply(function() { - ctrl.$setAttempted(ctrl.$invalid); - fn(scope, {$event:event}); - }); - }); - }; - } - }; - }]; - /** * @ngdoc directive * @name ng.directive:ngFocus