Skip to content

Commit f2af60c

Browse files
author
Gonzalo Ruiz de Villa
committed
fix(input,select): equality comparison is used to detect changes
When model changes are detected, a equality comparison with a local copy of the value ($modelValue). ngModelController provides the method $setCompareByEquality to change between equality and reference comparisons. Closes angular#1751
1 parent fc25a44 commit f2af60c

File tree

3 files changed

+26
-4
lines changed

3 files changed

+26
-4
lines changed

src/ng/directive/input.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
911911
this.$valid = true;
912912
this.$invalid = false;
913913
this.$name = $attr.name;
914+
this.$objectEquality = true;
914915

915916
var ngModelGet = $parse($attr.ngModel),
916917
ngModelSet = ngModelGet.assign;
@@ -948,6 +949,10 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
948949
addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);
949950
}
950951

952+
this.$setCompareByEquality = function (value) {
953+
this.$objectEquality = value;
954+
}
955+
951956
/**
952957
* @ngdoc function
953958
* @name ng.directive:ngModel.NgModelController#$setValidity
@@ -1038,8 +1043,8 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
10381043
value = fn(value);
10391044
});
10401045

1041-
if (this.$modelValue !== value) {
1042-
this.$modelValue = value;
1046+
if (this.$objectEquality ? !equals(this.$modelValue, value) : this.$modelValue !== value ) {
1047+
this.$modelValue = ctrl.$objectEquality ? copy(value) : value;
10431048
ngModelSet($scope, value);
10441049
forEach(this.$viewChangeListeners, function(listener) {
10451050
try {
@@ -1058,12 +1063,12 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
10581063
var value = ngModelGet($scope);
10591064

10601065
// if scope model value and ngModel value are out of sync
1061-
if (ctrl.$modelValue !== value) {
1066+
if (ctrl.$objectEquality ? !equals(ctrl.$modelValue, value) : ctrl.$modelValue !== value) {
10621067

10631068
var formatters = ctrl.$formatters,
10641069
idx = formatters.length;
10651070

1066-
ctrl.$modelValue = value;
1071+
ctrl.$modelValue = ctrl.$objectEquality ? copy(value) : value;
10671072
while(idx--) {
10681073
value = formatters[idx](value);
10691074
}

src/ng/directive/select.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
213213

214214
selectCtrl.init(ngModelCtrl, nullOption, unknownOption);
215215

216+
//select must compare objects by reference, not by equality
217+
ngModelCtrl.$setCompareByEquality(false);
218+
216219
// required validator
217220
if (multiple && (attr.required || attr.ngRequired)) {
218221
var requiredValidator = function(value) {

test/ng/directive/inputSpec.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,20 @@ describe('input', function() {
990990
});
991991

992992

993+
it("should detect changes in the values of an array", function () {
994+
var list = ['x', 'y', 'z'];
995+
compileInput('<input type="text" ng-model="list" ng-list />');
996+
scope.$apply(function() {
997+
scope.list = list;
998+
});
999+
expect(inputElm.val()).toBe('x, y, z');
1000+
scope.$apply(function() {
1001+
list.unshift('w');
1002+
});
1003+
expect(inputElm.val()).toBe('w, x, y, z');
1004+
});
1005+
1006+
9931007
xit('should require at least one item', function() {
9941008
compileInput('<input type="text" ng-model="list" ng-list required />');
9951009

0 commit comments

Comments
 (0)