mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-26 22:53:58 +00:00
fix(forms): remove control.$form and use nullFormCtrl
This commit is contained in:
parent
089c0f8b0e
commit
4806d28a29
3 changed files with 39 additions and 35 deletions
|
|
@ -4,7 +4,8 @@
|
||||||
var nullFormCtrl = {
|
var nullFormCtrl = {
|
||||||
$addControl: noop,
|
$addControl: noop,
|
||||||
$removeControl: noop,
|
$removeControl: noop,
|
||||||
$setValidity: noop
|
$setValidity: noop,
|
||||||
|
$setDirty: noop
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue