From 6f8aa1dbfdd26f4c28e900e53e98ccc0df59944a Mon Sep 17 00:00:00 2001 From: mohamed amr Date: Thu, 14 Apr 2016 02:32:19 +0200 Subject: [PATCH] fix(ngValue): set value property and attribute instead of setting attribute only input element reads the value from value property and override the value attribute so we need to set both Closes #14031 Closes #13984 BREAKING CHANGE: NgValue is no longer updating the "value attribute" only when the model change, because input element reads the value from "value attribute" only in case of "value property" has no value but when "value property" changed the input element will stop reading the value from "value attribute" and read it form the "value property". so the input value in the gui will not equal the value of the model, becuase the model update the "value attribute" only. Now ngValue updates both of "value attribute" and "value property" when the model change This shouldn't affect any application becuase this is a bug and input value in the gui should be updated when the model change --- src/ng/directive/input.js | 25 +++++++++++++++++++------ test/ng/directive/inputSpec.js | 16 ++++++++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js index 6b31f9998f21..731d3909d158 100644 --- a/src/ng/directive/input.js +++ b/src/ng/directive/input.js @@ -1701,6 +1701,10 @@ var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/; * so that when the element is selected, the {@link ngModel `ngModel`} of that element is set to * the bound value. * + * It can be used to achieve one-way binding of a given expression to the value of `element`, + * so that when the expression change the element is set to the bound value. + * + * * `ngValue` is useful when dynamically generating lists of radio buttons using * {@link ngRepeat `ngRepeat`}, as shown below. * @@ -1711,7 +1715,7 @@ var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/; * * @element input * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute - * of the `input` element + * and `value` property of the element * * @example @@ -1750,24 +1754,33 @@ var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/; */ var ngValueDirective = function() { + //helper function + var updateElementValue = function(element, attr, value) { + /** + * input use 'value attribute' as default value if 'value property has no value' + * but once set the 'value property' it will not read value from 'value attribute' + * so we set both the value attribute and property here to avoid this problem. + */ + attr.$set('value', value); + element.prop('value', value); + }; + return { restrict: 'A', priority: 100, compile: function(tpl, tplAttr) { if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) { return function ngValueConstantLink(scope, elm, attr) { - attr.$set('value', scope.$eval(attr.ngValue)); + var value = scope.$eval(attr.ngValue); + updateElementValue(elm, attr, value); }; } else { return function ngValueLink(scope, elm, attr) { scope.$watch(attr.ngValue, function valueWatchAction(value) { - attr.$set('value', value); + updateElementValue(elm, attr, value); }); }; } } }; }; - - - diff --git a/test/ng/directive/inputSpec.js b/test/ng/directive/inputSpec.js index 93efd7d30cfa..4b62df6a51b7 100644 --- a/test/ng/directive/inputSpec.js +++ b/test/ng/directive/inputSpec.js @@ -3046,6 +3046,22 @@ describe('input', function() { expect(inputElm[0].getAttribute('value')).toBe('something'); }); + they('should update the $prop "value" property and attribute after change the "value" property', { + input: '', + textarea: '' + }, function(tmpl) { + var element = helper.compileInput(tmpl); + + helper.changeInputValueTo('newValue'); + expect(element[0].value).toBe('newValue'); + expect(element[0].getAttribute('value')).toBeNull(); + + $rootScope.$apply(function() { + $rootScope.value = 'anotherValue'; + }); + expect(element[0].value).toBe('anotherValue'); + expect(element[0].getAttribute('value')).toBe('anotherValue'); + }); it('should evaluate and set constant expressions', function() { var inputElm = helper.compileInput('' +