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('' +