From b895c8037de4a9535581f0f2ac5a95e3463ffcc3 Mon Sep 17 00:00:00 2001 From: mohamed amr Date: Sat, 13 Feb 2016 02:29:59 +0200 Subject: [PATCH] fix(ngValue): set value property instead of attr in case of input element set value using property instead of attribute fixed #13984 --- src/.jshintrc | 1 + src/jqLite.js | 18 ++++++++++++++++++ src/ng/compile.js | 5 +++-- test/ng/directive/inputSpec.js | 20 ++++++++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/.jshintrc b/src/.jshintrc index fc2ae74034a5..fb8fdee9e3de 100644 --- a/src/.jshintrc +++ b/src/.jshintrc @@ -140,6 +140,7 @@ "jqLiteParseHTML": false, "jqLiteWrapNode": false, "getBooleanAttrName": false, + "getValueAttrName": false, "getAliasedAttrName": false, "createEventHandler": false, "JQLitePrototype": false, diff --git a/src/jqLite.js b/src/jqLite.js index da55bae864ad..12b6dedb5e04 100644 --- a/src/jqLite.js +++ b/src/jqLite.js @@ -15,6 +15,7 @@ addEventListenerFn: true, removeEventListenerFn: true, BOOLEAN_ATTR: true, + VALUE_ATTR: true, ALIASED_ATTR: true, */ @@ -577,6 +578,15 @@ var BOOLEAN_ELEMENTS = {}; forEach('input,select,option,textarea,button,form,details'.split(','), function(value) { BOOLEAN_ELEMENTS[value] = true; }); + +var VALUE_ATTR = {}; +VALUE_ATTR['value'] = 'value'; + +var VALUE_ELEMENTS = {}; +forEach('input,textarea'.split(','), function(value) { + VALUE_ELEMENTS[value] = true; +}); + var ALIASED_ATTR = { 'ngMinlength': 'minlength', 'ngMaxlength': 'maxlength', @@ -593,6 +603,14 @@ function getBooleanAttrName(element, name) { return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr; } +function getValueAttrName(element, name) { + // check dom last since we will most likely fail on name + var valueAttr = VALUE_ATTR[name.toLowerCase()]; + + // booleanAttr is here twice to minimize DOM access + return valueAttr && VALUE_ELEMENTS[nodeName_(element)] && valueAttr; +} + function getAliasedAttrName(name) { return ALIASED_ATTR[name]; } diff --git a/src/ng/compile.js b/src/ng/compile.js index fbbb32025595..bf04264828a2 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -1322,13 +1322,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { var node = this.$$element[0], booleanKey = getBooleanAttrName(node, key), + valueKey = getValueAttrName(node, key), aliasedKey = getAliasedAttrName(key), observer = key, nodeName; - if (booleanKey) { + if (booleanKey || valueKey) { this.$$element.prop(key, value); - attrName = booleanKey; + attrName = booleanKey ? booleanKey : valueKey; } else if (aliasedKey) { this[aliasedKey] = value; observer = aliasedKey; diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index 93efd7d30cfa..06c33d07d3f6 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -3046,6 +3046,26 @@ describe('input', function() { expect(inputElm[0].getAttribute('value')).toBe('something'); }); + it('should update the input "value" property and attribute after change the "value" property', function() { + var inputElm = helper.compileInput(''); + + $rootScope.$apply(function() { + $rootScope.value = 'something'; + }); + expect(inputElm[0].value).toBe('something'); + expect(inputElm[0].getAttribute('value')).toBe('something'); + + helper.changeInputValueTo('newValue'); + + $rootScope.$apply(function() { + $rootScope.value = 'anotherValue'; + }); + expect(inputElm[0].value).toBe('anotherValue'); + expect(inputElm[0].getAttribute('value')).toBe('anotherValue'); + + + }); + it('should evaluate and set constant expressions', function() { var inputElm = helper.compileInput('' +