fix(ngModel): allow non-assignable binding when getterSetter is used

Closes #8704
This commit is contained in:
Shahar Talmi
2014-08-22 04:18:06 +03:00
committed by Brian Ford
parent 474a0337bd
commit ab878a6c03
2 changed files with 23 additions and 31 deletions

View File

@@ -1599,10 +1599,14 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
pendingDebounce = null,
ctrl = this;
if (!ngModelSet) {
throw $ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
$attr.ngModel, startingTag($element));
}
this.$$setOptions = function(options) {
ctrl.$options = options;
if (!ngModelSet && (!options || !options.getterSetter)) {
throw $ngModelMinErr('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
$attr.ngModel, startingTag($element));
}
};
/**
* @ngdoc method
@@ -2293,16 +2297,12 @@ var ngModelDirective = function() {
controller: NgModelController,
link: {
pre: function(scope, element, attr, ctrls) {
// Pass the ng-model-options to the ng-model controller
if (ctrls[2]) {
ctrls[0].$options = ctrls[2].$options;
}
// notify others, especially parent forms
var modelCtrl = ctrls[0],
formCtrl = ctrls[1] || nullFormCtrl;
modelCtrl.$$setOptions(ctrls[2] && ctrls[2].$options);
// notify others, especially parent forms
formCtrl.$addControl(modelCtrl);
scope.$on('$destroy', function() {

View File

@@ -32,26 +32,6 @@ describe('NgModelController', function() {
});
it('should fail on non-assignable model binding', inject(function($controller) {
var exception;
try {
$controller(NgModelController, {
$scope: null,
$element: jqLite('<input ng-model="1+2">'),
$attrs: {
ngModel: '1+2'
}
});
} catch (e) {
exception = e;
}
expect(exception.message).
toMatch(/^\[ngModel:nonassign\] Expression '1\+2' is non\-assignable\. Element: <input( value="")? ng-model="1\+2">/);
}));
it('should init the properties', function() {
expect(ctrl.$untouched).toBe(true);
expect(ctrl.$touched).toBe(false);
@@ -1581,6 +1561,18 @@ describe('input', function() {
expect(scope.name).toBe('d');
});
it('should fail on non-assignable model binding if getterSetter is false', function() {
expect(function() {
compileInput('<input type="text" ng-model="accessor(user, \'name\')" />');
}).toThrowMinErr('ngModel', 'nonassign', 'Expression \'accessor(user, \'name\')\' is non-assignable.');
});
it('should not fail on non-assignable model binding if getterSetter is true', function() {
compileInput(
'<input type="text" ng-model="accessor(user, \'name\')" '+
'ng-model-options="{ getterSetter: true }" />');
});
});
it('should allow complex reference binding', function() {