fix(ngForm): alias name||ngForm

form directive was requiring name attribute even when invoked as attribute, resulting in unnecessary duplication
This commit is contained in:
Misko Hevery 2012-03-15 14:08:49 -07:00
parent 21e74c2d2e
commit 823adb2319
2 changed files with 54 additions and 26 deletions

View file

@ -31,10 +31,10 @@ var nullFormCtrl = {
* of `FormController`. * of `FormController`.
* *
*/ */
FormController.$inject = ['name', '$element', '$attrs']; FormController.$inject = ['$element', '$attrs'];
function FormController(name, element, attrs) { function FormController(element, attrs) {
var form = this, var form = this,
parentForm = element.parent().inheritedData('$formController') || nullFormCtrl, parentForm = element.parent().controller('form') || nullFormCtrl,
invalidCount = 0, // used to easily determine if we are valid invalidCount = 0, // used to easily determine if we are valid
errors = form.$error = {}; errors = form.$error = {};
@ -45,9 +45,6 @@ function FormController(name, element, attrs) {
form.$valid = true; form.$valid = true;
form.$invalid = false; form.$invalid = false;
// publish the form into scope
name(this);
parentForm.$addControl(form); parentForm.$addControl(form);
// Setup initial state of the control // Setup initial state of the control
@ -130,9 +127,24 @@ function FormController(name, element, attrs) {
/** /**
* @ngdoc directive
* @name angular.module.ng.$compileProvider.directive.ng-form
* @restrict EAC
*
* @description
* Nestable alias of {@link angular.module.ng.$compileProvider.directive.form `form`} directive. HTML
* does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
* sub-group of controls needs to be determined.
*
* @param {string=} ng-form|name Name of the form. If specified, the form controller will be published into
* related scope, under this name.
*
*/
/**
* @ngdoc directive * @ngdoc directive
* @name angular.module.ng.$compileProvider.directive.form * @name angular.module.ng.$compileProvider.directive.form
* @restrict EA * @restrict E
* *
* @description * @description
* Directive that instantiates * Directive that instantiates
@ -141,12 +153,12 @@ function FormController(name, element, attrs) {
* If `name` attribute is specified, the form controller is published onto the current scope under * If `name` attribute is specified, the form controller is published onto the current scope under
* this name. * this name.
* *
* # Alias: `ng-form` * # Alias: {@link angular.module.ng.$compileProvider.directive.ng-form `ng-form`}
* *
* In angular forms can be nested. This means that the outer form is valid when all of the child * In angular forms can be nested. This means that the outer form is valid when all of the child
* forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this * forms are valid as well. However browsers do not allow nesting of `<form>` elements, for this
* reason angular provides `<ng-form>` alias which behaves identical to `<form>` but allows * reason angular provides {@link angular.module.ng.$compileProvider.directive.ng-form `ng-form`} alias
* element nesting. * which behaves identical to `<form>` but allows form nesting.
* *
* *
* # CSS classes * # CSS classes
@ -218,25 +230,31 @@ function FormController(name, element, attrs) {
</doc:scenario> </doc:scenario>
</doc:example> </doc:example>
*/ */
var formDirectiveDev = { var formDirectiveDir = {
name: 'form', name: 'form',
restrict: 'E', restrict: 'E',
inject: {
name: 'accessor'
},
controller: FormController, controller: FormController,
compile: function() { compile: function() {
return { return {
pre: function(scope, formElement, attr, controller) { pre: function(scope, formElement, attr, controller) {
formElement.bind('submit', function(event) { if (!attr.action) {
if (!attr.action) event.preventDefault(); formElement.bind('submit', function(event) {
}); event.preventDefault();
});
}
var parentFormCtrl = formElement.parent().inheritedData('$formController'); var parentFormCtrl = formElement.parent().controller('form'),
alias = attr.name || attr.ngForm;
if (alias) {
scope[alias] = controller;
}
if (parentFormCtrl) { if (parentFormCtrl) {
formElement.bind('$destroy', function() { formElement.bind('$destroy', function() {
parentFormCtrl.$removeControl(controller); parentFormCtrl.$removeControl(controller);
if (attr.name) delete scope[attr.name]; if (alias) {
scope[alias] = undefined;
}
extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
}); });
} }
@ -245,5 +263,5 @@ var formDirectiveDev = {
} }
}; };
var formDirective = valueFn(formDirectiveDev); var formDirective = valueFn(formDirectiveDir);
var ngFormDirective = valueFn(extend(copy(formDirectiveDev), {restrict:'EAC'})); var ngFormDirective = valueFn(extend(copy(formDirectiveDir), {restrict: 'EAC'}));

View file

@ -33,9 +33,9 @@ describe('form', function() {
it('should remove the widget when element removed', function() { it('should remove the widget when element removed', function() {
doc = $compile( doc = $compile(
'<form name="myForm">' + '<form name="myForm">' +
'<input type="text" name="alias" ng-model="value" store-model-ctrl/>' + '<input type="text" name="alias" ng-model="value" store-model-ctrl/>' +
'</form>')(scope); '</form>')(scope);
var form = scope.myForm; var form = scope.myForm;
control.$setValidity('required', false); control.$setValidity('required', false);
@ -48,6 +48,17 @@ describe('form', function() {
}); });
it('should use ng-form as form name', function() {
doc = $compile(
'<div ng-form="myForm">' +
'<input type="text" name="alias" ng-model="value"/>' +
'</div>')(scope);
expect(scope.myForm).toBeDefined();
expect(scope.myForm.alias).toBeDefined();
});
it('should prevent form submission', function() { it('should prevent form submission', function() {
var startingUrl = '' + window.location; var startingUrl = '' + window.location;
doc = jqLite('<form name="myForm"><input type="submit" value="submit" />'); doc = jqLite('<form name="myForm"><input type="submit" value="submit" />');
@ -89,8 +100,7 @@ describe('form', function() {
it('should allow form name to be an expression', function() { it('should allow form name to be an expression', function() {
doc = $compile('<form name="obj.myForm"></form>')(scope); doc = $compile('<form name="obj.myForm"></form>')(scope);
expect(scope.obj).toBeDefined(); expect(scope['obj.myForm']).toBeTruthy();
expect(scope.obj.myForm).toBeTruthy();
}); });