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

feat(ngModel): public method to force run model -> view binding pipeline #12818

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
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
26 changes: 21 additions & 5 deletions src/ng/directive/ngModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,21 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
*/
this.$render = noop;

/**
* @ngdoc method
* @name ngModel.NgModelController#$forceModelToViewBound
*
* @description
* This might be called to force update model -> view binding without changing actual model
*
* It will trigger $formatters pipeline, and in case of changed $viewValue, will run validators and
* update the UI.
*
* For instance you might use this to change the input's value, but keep the original scope.value the same.
*/
this.$forceModelToViewBound = ngModelWatch.bind(this, true);


/**
* @ngdoc method
* @name ngModel.NgModelController#$isEmpty
Expand Down Expand Up @@ -814,14 +829,15 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
// -> scope value did not change since the last digest as
// ng-change executes in apply phase
// 4. view should be changed back to 'a'
$scope.$watch(function ngModelWatch() {
$scope.$watch(ngModelWatch);
function ngModelWatch() {
var modelValue = ngModelGet($scope);

// if scope model value and ngModel value are out of sync
// if forced to run formatters and validators, or scope model value and ngModel value are out of sync
// TODO(perf): why not move this to the action fn?
if (modelValue !== ctrl.$modelValue &&
if (arguments[0] === true || (modelValue !== ctrl.$modelValue &&
// checks for NaN is needed to allow setting the model to NaN when there's an asyncValidator
(ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue)
(ctrl.$modelValue === ctrl.$modelValue || modelValue === modelValue))
) {
ctrl.$modelValue = ctrl.$$rawModelValue = modelValue;
parserValid = undefined;
Expand All @@ -842,7 +858,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
}

return modelValue;
});
}
}];


Expand Down
13 changes: 13 additions & 0 deletions test/ng/directive/ngModelSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,19 @@ describe('ngModel', function() {
});


it('should be possible to force model -> view binding from ngModelController', function() {
var spyFormatter = jasmine.createSpy('spyValidator');
ctrl.$formatters = ctrl.$formatters.concat(spyFormatter);
spyOn(ctrl, '$render');
spyOn(ctrl, '$$runValidators');

ctrl.$forceModelToViewBound();
expect(spyFormatter).toHaveBeenCalledOnce();
expect(ctrl.$render).toHaveBeenCalledOnce();
expect(ctrl.$$runValidators).toHaveBeenCalledOnce();
});


it('should clear the view even if invalid', function() {
spyOn(ctrl, '$render');

Expand Down