Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix(ngModelOptions): do not trigger digest during debounce #8911

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 11 additions & 19 deletions src/ng/directive/input.js
Original file line number Diff line number Diff line change
@@ -956,13 +956,7 @@ function baseInputType(scope, element, attr, ctrl, $sniffer, $browser) {
// value, so it may be necessary to revalidate (by calling $setViewValue again) even if the
// control's value is the same empty value twice in a row.
if (ctrl.$viewValue !== value || (value === '' && ctrl.$$hasNativeValidators)) {
if (scope.$root.$$phase) {
ctrl.$setViewValue(value, event);
} else {
scope.$apply(function() {
ctrl.$setViewValue(value, event);
});
}
ctrl.$setViewValue(value, event);
}
};

@@ -1173,9 +1167,7 @@ function radioInputType(scope, element, attr, ctrl) {

var listener = function(ev) {
if (element[0].checked) {
scope.$apply(function() {
ctrl.$setViewValue(attr.value, ev && ev.type);
});
ctrl.$setViewValue(attr.value, ev && ev.type);
}
};

@@ -1207,9 +1199,7 @@ function checkboxInputType(scope, element, attr, ctrl, $sniffer, $browser, $filt
var falseValue = parseConstantExpr($parse, scope, 'ngFalseValue', attr.ngFalseValue, false);

var listener = function(ev) {
scope.$apply(function() {
ctrl.$setViewValue(element[0].checked, ev && ev.type);
});
ctrl.$setViewValue(element[0].checked, ev && ev.type);
};

element.on('click', listener);
@@ -1588,8 +1578,8 @@ var VALID_CLASS = 'ng-valid',
*
*
*/
var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout',
function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout) {
var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', '$animate', '$timeout', '$rootScope',
function($scope, $exceptionHandler, $attr, $element, $parse, $animate, $timeout, $rootScope) {
this.$viewValue = Number.NaN;
this.$modelValue = Number.NaN;
this.$validators = {};
@@ -2112,8 +2102,12 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
pendingDebounce = $timeout(function() {
ctrl.$commitViewValue();
}, debounceDelay);
} else {
} else if ($rootScope.$$phase) {
ctrl.$commitViewValue();
} else {
$scope.$apply(function() {
ctrl.$commitViewValue();
});
}
};

@@ -2330,9 +2324,7 @@ var ngModelDirective = function() {
var modelCtrl = ctrls[0];
if (modelCtrl.$options && modelCtrl.$options.updateOn) {
element.on(modelCtrl.$options.updateOn, function(ev) {
scope.$apply(function() {
modelCtrl.$$debounceViewValueCommit(ev && ev.type);
});
modelCtrl.$$debounceViewValueCommit(ev && ev.type);
});
}

16 changes: 16 additions & 0 deletions test/ng/directive/inputSpec.js
Original file line number Diff line number Diff line change
@@ -1414,6 +1414,22 @@ describe('input', function() {

}));

it('should not trigger digest while debouncing', inject(function($timeout) {
compileInput(
'<input type="text" ng-model="name" name="alias" '+
'ng-model-options="{ debounce: 10000 }"'+
'/>');

var watchSpy = jasmine.createSpy('watchSpy');
scope.$watch(watchSpy);

changeInputValueTo('a');
expect(watchSpy).not.toHaveBeenCalled();

$timeout.flush(10000);
expect(watchSpy).toHaveBeenCalled();
}));

it('should allow selecting different debounce timeouts for each event',
inject(function($timeout) {
compileInput(