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

Commit ab878a6

Browse files
shahatabtford
authored andcommitted
fix(ngModel): allow non-assignable binding when getterSetter is used
Closes #8704
1 parent 474a033 commit ab878a6

File tree

2 files changed

+23
-31
lines changed

2 files changed

+23
-31
lines changed

src/ng/directive/input.js

+11-11
Original file line numberDiff line numberDiff line change
@@ -1599,10 +1599,14 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
15991599
pendingDebounce = null,
16001600
ctrl = this;
16011601

1602-
if (!ngModelSet) {
1603-
throw $ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
1604-
$attr.ngModel, startingTag($element));
1605-
}
1602+
this.$$setOptions = function(options) {
1603+
ctrl.$options = options;
1604+
1605+
if (!ngModelSet && (!options || !options.getterSetter)) {
1606+
throw $ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
1607+
$attr.ngModel, startingTag($element));
1608+
}
1609+
};
16061610

16071611
/**
16081612
* @ngdoc method
@@ -2293,16 +2297,12 @@ var ngModelDirective = function() {
22932297
controller: NgModelController,
22942298
link: {
22952299
pre: function(scope, element, attr, ctrls) {
2296-
// Pass the ng-model-options to the ng-model controller
2297-
if (ctrls[2]) {
2298-
ctrls[0].$options = ctrls[2].$options;
2299-
}
2300-
2301-
// notify others, especially parent forms
2302-
23032300
var modelCtrl = ctrls[0],
23042301
formCtrl = ctrls[1] || nullFormCtrl;
23052302

2303+
modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);
2304+
2305+
// notify others, especially parent forms
23062306
formCtrl.$addControl(modelCtrl);
23072307

23082308
scope.$on('$destroy', function() {

test/ng/directive/inputSpec.js

+12-20
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,6 @@ describe('NgModelController', function() {
3232
});
3333

3434

35-
it('should fail on non-assignable model binding', inject(function($controller) {
36-
var exception;
37-
38-
try {
39-
$controller(NgModelController, {
40-
$scope: null,
41-
$element: jqLite('<input ng-model="1+2">'),
42-
$attrs: {
43-
ngModel: '1+2'
44-
}
45-
});
46-
} catch (e) {
47-
exception = e;
48-
}
49-
50-
expect(exception.message).
51-
toMatch(/^\[ngModel:nonassign\] Expression '1\+2' is non\-assignable\. Element: <input( value="")? ng-model="1\+2">/);
52-
}));
53-
54-
5535
it('should init the properties', function() {
5636
expect(ctrl.$untouched).toBe(true);
5737
expect(ctrl.$touched).toBe(false);
@@ -1581,6 +1561,18 @@ describe('input', function() {
15811561
expect(scope.name).toBe('d');
15821562
});
15831563

1564+
it('should fail on non-assignable model binding if getterSetter is false', function() {
1565+
expect(function() {
1566+
compileInput('<input type="text" ng-model="accessor(user, \'name\')" />');
1567+
}).toThrowMinErr('ngModel', 'nonassign', 'Expression \'accessor(user, \'name\')\' is non-assignable.');
1568+
});
1569+
1570+
it('should not fail on non-assignable model binding if getterSetter is true', function() {
1571+
compileInput(
1572+
'<input type="text" ng-model="accessor(user, \'name\')" '+
1573+
'ng-model-options="{ getterSetter: true }" />');
1574+
});
1575+
15841576
});
15851577

15861578
it('should allow complex reference binding', function() {

0 commit comments

Comments
 (0)