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

Commit 2fa87c1

Browse files
committed
feat(ngModel) Allow running the formatters without a change to the modelValue
Fixes #3407
1 parent 1a7e9de commit 2fa87c1

File tree

2 files changed

+52
-12
lines changed

2 files changed

+52
-12
lines changed

src/ng/directive/ngModel.js

+26-12
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,28 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
799799
}
800800
};
801801

802+
function formatValue(modelValue) {
803+
var formatters = ctrl.$formatters,
804+
idx = formatters.length;
805+
806+
var viewValue = modelValue;
807+
while (idx--) {
808+
viewValue = formatters[idx](viewValue);
809+
}
810+
811+
return viewValue;
812+
}
813+
814+
this.$runFormatters = function() {
815+
var modelValue = this.$modelValue,
816+
viewValue = formatValue(this.$modelValue);
817+
818+
if (this.$viewValue !== viewValue) {
819+
this.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
820+
this.$render();
821+
}
822+
};
823+
802824
// model -> value
803825
// Note: we cannot use a normal scope.$watch as we want to detect the following:
804826
// 1. scope value is 'a'
@@ -814,19 +836,11 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
814836
// TODO(perf): why not move this to the action fn?
815837
if (modelValue !== ctrl.$modelValue) {
816838
ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;
839+
var oldViewValue = ctrl.$viewValue;
817840

818-
var formatters = ctrl.$formatters,
819-
idx = formatters.length;
820-
821-
var viewValue = modelValue;
822-
while (idx--) {
823-
viewValue = formatters[idx](viewValue);
824-
}
825-
if (ctrl.$viewValue !== viewValue) {
826-
ctrl.$viewValue = ctrl.$$lastCommittedViewValue = viewValue;
827-
ctrl.$render();
828-
829-
ctrl.$$runValidators(undefined, modelValue, viewValue, noop);
841+
ctrl.$runFormatters();
842+
if (ctrl.$viewValue !== oldViewValue) {
843+
ctrl.$$runValidators(undefined, modelValue, ctrl.$viewValue, noop);
830844
}
831845
}
832846

test/ng/directive/ngModelSpec.js

+26
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,32 @@ describe('ngModel', function() {
578578

579579
dealoc(form);
580580
}));
581+
582+
describe('$runFormatters', function() {
583+
it('should reformat the value', function() {
584+
spyOn(ctrl, '$render');
585+
ctrl.$validators.spyValidator = jasmine.createSpy('spyValidator');
586+
scope.$apply('value = "first"');
587+
ctrl.$formatters.push(function(value) {
588+
return 'change';
589+
});
590+
ctrl.$runFormatters();
591+
expect(ctrl.$viewValue).toBe('change');
592+
});
593+
594+
it('should not rerender nor validate in case view value is not changed', function() {
595+
ctrl.$formatters.push(function(value) {
596+
return 'nochange';
597+
});
598+
599+
spyOn(ctrl, '$render');
600+
ctrl.$validators.spyValidator = jasmine.createSpy('spyValidator');
601+
scope.$apply('value = "first"');
602+
ctrl.$runFormatters();
603+
expect(ctrl.$validators.spyValidator).toHaveBeenCalledOnce();
604+
expect(ctrl.$render).toHaveBeenCalledOnce();
605+
});
606+
});
581607
});
582608

583609

0 commit comments

Comments
 (0)