fix(forms): remove control.$form and use nullFormCtrl

This commit is contained in:
Igor Minar 2012-03-13 14:56:52 -07:00
parent 089c0f8b0e
commit 4806d28a29
3 changed files with 39 additions and 35 deletions

View file

@ -4,7 +4,8 @@
var nullFormCtrl = { var nullFormCtrl = {
$addControl: noop, $addControl: noop,
$removeControl: noop, $removeControl: noop,
$setValidity: noop $setValidity: noop,
$setDirty: noop
} }
/** /**

View file

@ -742,8 +742,8 @@ var inputDirective = [function() {
* @description * @description
* *
*/ */
var NgModelController = ['$scope', '$exceptionHandler', '$attrs', 'ngModel', var NgModelController = ['$scope', '$exceptionHandler', '$attrs', 'ngModel', '$element',
function($scope, $exceptionHandler, $attr, ngModel) { function($scope, $exceptionHandler, $attr, ngModel, $element) {
this.$viewValue = Number.NaN; this.$viewValue = Number.NaN;
this.$modelValue = Number.NaN; this.$modelValue = Number.NaN;
this.$parsers = []; this.$parsers = [];
@ -757,6 +757,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', 'ngModel',
this.$render = noop; this.$render = noop;
this.$name = $attr.name; this.$name = $attr.name;
var parentForm = $element.inheritedData('$formController') || nullFormCtrl;
/** /**
* @ngdoc function * @ngdoc function
@ -789,9 +790,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', 'ngModel',
this.$valid = false; this.$valid = false;
} }
if (this.$form) { parentForm.$setValidity(validationErrorKey, isValid, this);
this.$form.$setValidity(validationErrorKey, isValid, this);
}
}; };
@ -819,7 +818,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', 'ngModel',
if (this.$pristine) { if (this.$pristine) {
this.$dirty = true; this.$dirty = true;
this.$pristine = false; this.$pristine = false;
if (this.$form) this.$form.$setDirty(); parentForm.$setDirty();
} }
forEach(this.$parsers, function(fn) { forEach(this.$parsers, function(fn) {
@ -907,11 +906,9 @@ var ngModelDirective = [function() {
// notify others, especially parent forms // notify others, especially parent forms
var modelCtrl = ctrls[0], var modelCtrl = ctrls[0],
formCtrl = ctrls[1]; formCtrl = ctrls[1] || nullFormCtrl;
modelCtrl.$form = formCtrl; formCtrl.$addControl(modelCtrl);
if (formCtrl) formCtrl.$addControl(modelCtrl);
forEach(['valid', 'invalid', 'pristine', 'dirty'], function(name) { forEach(['valid', 'invalid', 'pristine', 'dirty'], function(name) {
scope.$watch(function() { scope.$watch(function() {
@ -922,7 +919,7 @@ var ngModelDirective = [function() {
}); });
element.bind('$destroy', function() { element.bind('$destroy', function() {
if (formCtrl) formCtrl.$removeControl(modelCtrl); formCtrl.$removeControl(modelCtrl);
}); });
} }
}; };

View file

@ -1,15 +1,24 @@
'use strict'; 'use strict';
describe('NgModelController', function() { describe('NgModelController', function() {
var ctrl, scope, ngModelAccessor; var ctrl, scope, ngModelAccessor, element, parentFormCtrl;
beforeEach(inject(function($rootScope, $controller) { beforeEach(inject(function($rootScope, $controller) {
var attrs = {name: 'testAlias'}; var attrs = {name: 'testAlias'};
parentFormCtrl = {
$setValidity: jasmine.createSpy('$setValidity'),
$setDirty: jasmine.createSpy('$setDirty')
}
element = jqLite('<form><input></form>');
element.data('$formController', parentFormCtrl);
scope = $rootScope; scope = $rootScope;
ngModelAccessor = jasmine.createSpy('ngModel accessor'); ngModelAccessor = jasmine.createSpy('ngModel accessor');
ctrl = $controller(NgModelController, {$scope: scope, ngModel: ngModelAccessor, $attrs: attrs}); ctrl = $controller(NgModelController, {
$scope: scope, $element: element.find('input'), ngModel: ngModelAccessor, $attrs: attrs
});
// mock accessor (locals) // mock accessor (locals)
ngModelAccessor.andCallFake(function(val) { ngModelAccessor.andCallFake(function(val) {
if (isDefined(val)) scope.value = val; if (isDefined(val)) scope.value = val;
@ -18,6 +27,11 @@ describe('NgModelController', function() {
})); }));
afterEach(function() {
dealoc(element);
});
it('should init the properties', function() { it('should init the properties', function() {
expect(ctrl.$dirty).toBe(false); expect(ctrl.$dirty).toBe(false);
expect(ctrl.$pristine).toBe(true); expect(ctrl.$pristine).toBe(true);
@ -37,15 +51,13 @@ describe('NgModelController', function() {
describe('setValidity', function() { describe('setValidity', function() {
it('should propagate invalid to the parent form only when valid', function() { it('should propagate invalid to the parent form only when valid', function() {
var spy = jasmine.createSpy('setValidity'); expect(parentFormCtrl.$setValidity).not.toHaveBeenCalled();
ctrl.$form = {$setValidity: spy};
ctrl.$setValidity('ERROR', false); ctrl.$setValidity('ERROR', false);
expect(spy).toHaveBeenCalledOnceWith('ERROR', false, ctrl); expect(parentFormCtrl.$setValidity).toHaveBeenCalledOnceWith('ERROR', false, ctrl);
spy.reset(); parentFormCtrl.$setValidity.reset();
ctrl.$setValidity('ERROR', false); ctrl.$setValidity('ERROR', false);
expect(spy).not.toHaveBeenCalled(); expect(parentFormCtrl.$setValidity).not.toHaveBeenCalled();
}); });
@ -78,17 +90,14 @@ describe('NgModelController', function() {
it('should emit $valid only when $invalid', function() { it('should emit $valid only when $invalid', function() {
var spy = jasmine.createSpy('setValidity');
ctrl.$form = {$setValidity: spy};
ctrl.$setValidity('ERROR', true); ctrl.$setValidity('ERROR', true);
expect(spy).not.toHaveBeenCalled(); expect(parentFormCtrl.$setValidity).not.toHaveBeenCalled();
ctrl.$setValidity('ERROR', false); ctrl.$setValidity('ERROR', false);
expect(spy).toHaveBeenCalledOnceWith('ERROR', false, ctrl); expect(parentFormCtrl.$setValidity).toHaveBeenCalledOnceWith('ERROR', false, ctrl);
spy.reset(); parentFormCtrl.$setValidity.reset();
ctrl.$setValidity('ERROR', true); ctrl.$setValidity('ERROR', true);
expect(spy).toHaveBeenCalledOnceWith('ERROR', true, ctrl); expect(parentFormCtrl.$setValidity).toHaveBeenCalledOnceWith('ERROR', true, ctrl);
}); });
}); });
@ -147,20 +156,17 @@ describe('NgModelController', function() {
}); });
it('should call parentForm.setDirty only when pristine', function() { it('should call parentForm.$setDirty only when pristine', function() {
var spy = jasmine.createSpy('setDirty');
ctrl.$form = {$setDirty: spy};
ctrl.$setViewValue(''); ctrl.$setViewValue('');
expect(ctrl.$pristine).toBe(false); expect(ctrl.$pristine).toBe(false);
expect(ctrl.$dirty).toBe(true); expect(ctrl.$dirty).toBe(true);
expect(spy).toHaveBeenCalledOnce(); expect(parentFormCtrl.$setDirty).toHaveBeenCalledOnce();
spy.reset(); parentFormCtrl.$setDirty.reset();
ctrl.$setViewValue(''); ctrl.$setViewValue('');
expect(ctrl.$pristine).toBe(false); expect(ctrl.$pristine).toBe(false);
expect(ctrl.$dirty).toBe(true); expect(ctrl.$dirty).toBe(true);
expect(spy).not.toHaveBeenCalled(); expect(parentFormCtrl.$setDirty).not.toHaveBeenCalled();
}); });
}); });