aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/Angular.js10
-rw-r--r--src/Compiler.js1
-rw-r--r--src/Validators.js31
-rw-r--r--src/Widgets.js8
-rw-r--r--test/ValidatorsTest.js27
-rw-r--r--test/widgetsSpec.js4
6 files changed, 50 insertions, 31 deletions
diff --git a/src/Angular.js b/src/Angular.js
index 12293ddb..e49eb9a9 100644
--- a/src/Angular.js
+++ b/src/Angular.js
@@ -228,6 +228,16 @@ function escapeHtml(html) {
replace(/>/g, '>');
}
+function elementDecorateError(element, error) {
+ if (error) {
+ element.addClass(NG_VALIDATION_ERROR);
+ element.attr(NG_ERROR, error);
+ } else {
+ element.removeClass(NG_VALIDATION_ERROR);
+ element.removeAttr(NG_ERROR);
+ }
+}
+
function escapeAttr(html) {
if (!html || !html.replace)
return html;
diff --git a/src/Compiler.js b/src/Compiler.js
index 923f7b2f..e97fb112 100644
--- a/src/Compiler.js
+++ b/src/Compiler.js
@@ -93,6 +93,7 @@ Compiler.prototype = {
rawElement = jqLite(rawElement);
var template = this.templatize(rawElement) || new Template();
return function(element, parentScope){
+ element = jqLite(element);
parentScope = parentScope || {};
var scope = createScope(parentScope);
parentScope.$root = parentScope.$root || scope;
diff --git a/src/Validators.js b/src/Validators.js
index 662145c0..ecf21a01 100644
--- a/src/Validators.js
+++ b/src/Validators.js
@@ -82,29 +82,30 @@ foreach({
},
'asynchronous': function(text, asynchronousFn) {
- var stateKey = '$validateState';
- var lastKey = '$lastKey';
- var obj = this['$element'];
- var stateCache = obj[stateKey] = obj[stateKey] || {};
- var state = stateCache[text];
- var updateView = this['$updateView'];
- obj[lastKey] = text;
+ var element = this['$element'];
+ var cache = element.data('$validateState');
+ if (!cache) {
+ cache = { state: {}};
+ element.data('$validateState', cache);
+ }
+ var state = cache.state[text];
+ cache.lastKey = text;
if (state === undefined) {
// we have never seen this before, Request it
- jqLite(obj).addClass('ng-input-indicator-wait');
- state = stateCache[text] = null;
- asynchronousFn(text, function(error){
- state = stateCache[text] = error ? error : false;
- if (stateCache[obj[lastKey]] !== null) {
- jqLite(obj).removeClass('ng-input-indicator-wait');
+ element.addClass('ng-input-indicator-wait');
+ state = cache.state[text] = null;
+ (asynchronousFn || noop)(text, function(error){
+ state = cache.state[text] = error ? error : false;
+ if (cache.state[cache.lastKey] !== null) {
+ element.removeClass('ng-input-indicator-wait');
}
- updateView();
+ elementDecorateError(element, error);
});
}
if (state === null){
// request in flight, mark widget invalid, but don't show it to user
- this['$invalidWidgets'].push(this.$element);
+ (this['$invalidWidgets']||[]).push(this.$element);
}
return state;
}
diff --git a/src/Widgets.js b/src/Widgets.js
index b5222ac7..870468d3 100644
--- a/src/Widgets.js
+++ b/src/Widgets.js
@@ -28,13 +28,7 @@ function valueAccessor(scope, element) {
function validate(value) {
var error = required && !trim(value) ? "Required" : validator({self:scope, scope:{get:scope.$get, set:scope.$set}}, value);
if (error !== lastError) {
- if (error) {
- element.addClass(NG_VALIDATION_ERROR);
- element.attr(NG_ERROR, error);
- } else {
- element.removeClass(NG_VALIDATION_ERROR);
- element.removeAttr(NG_ERROR);
- }
+ elementDecorateError(element, error);
lastError = error;
}
return value;
diff --git a/test/ValidatorsTest.js b/test/ValidatorsTest.js
index 971ff0bb..37be526d 100644
--- a/test/ValidatorsTest.js
+++ b/test/ValidatorsTest.js
@@ -91,24 +91,35 @@ describe('Validator:asynchronous', function(){
value = null;
fn = null;
self = {
- $element:jqLite('<input />')[0],
+ $element:jqLite('<input />'),
$invalidWidgets:[],
$updateView: noop
};
});
- xit('should make a request and show spinner', function(){
- var x = compile('<input name="name" ng-validate="asynchronous:asyncFn"/>');
- var asyncFn = function(v,f){value=v; fn=f;};
- var input = x.node.find(":input");
- x.scope.$set("asyncFn", asyncFn);
- x.scope.$set("name", "misko");
- x.scope.$eval();
+ afterEach(function(){
+ if (self.$element) self.$element.remove();
+ var oldCache = jqCache;
+ jqCache = {};
+ expect(size(oldCache)).toEqual(0);
+ });
+
+ it('should make a request and show spinner', function(){
+ var value, fn;
+ var scope = angular.compile('<input type="text" name="name" ng-validate="asynchronous:asyncFn"/>');
+ scope.$init();
+ var input = scope.$element;
+ scope.asyncFn = function(v,f){
+ value=v; fn=f;
+ };
+ scope.name = "misko";
+ scope.$eval();
expect(value).toEqual('misko');
expect(input.hasClass('ng-input-indicator-wait')).toBeTruthy();
fn("myError");
expect(input.hasClass('ng-input-indicator-wait')).toBeFalsy();
expect(input.attr('ng-error')).toEqual("myError");
+ scope.$element.remove();
});
it("should not make second request to same value", function(){
diff --git a/test/widgetsSpec.js b/test/widgetsSpec.js
index dd65b5bd..152b01f3 100644
--- a/test/widgetsSpec.js
+++ b/test/widgetsSpec.js
@@ -15,7 +15,9 @@ describe("input widget", function(){
afterEach(function(){
if (element) element.remove();
- expect(size(jqCache)).toEqual(0);
+ var oldCache = jqCache;
+ jqCache = {};
+ expect(size(oldCache)).toEqual(0);
});
it('should input-text auto init and handle keyup/change events', function(){