'use strict'; /** * @ngdoc widget * @name angular.widget.form * * @description * Angular widget that creates a form scope using the * {@link angular.module.ng.$formFactory $formFactory} API. The resulting form scope instance is * attached to the DOM element using the jQuery `.data()` method under the `$form` key. * See {@link guide/dev_guide.forms forms} on detailed discussion of forms and widgets. * * * # Alias: `ng:form` * * 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 `
` elements, for this * reason angular provides `` alias which behaves identical to `` but allows * element nesting. * * * # Submitting a form and preventing default action * * Since the role of forms in client-side Angular applications is different than in old-school * roundtrip apps, it is desirable for the browser not to translate the form submission into a full * page reload that sends the data to the server. Instead some javascript logic should be triggered * to handle the form submission in application specific way. * * For this reason, Angular prevents the default action (form submission to the server) unless the * `` element has an `action` attribute specified. * * You can use one of the following two ways to specify what javascript method should be called when * a form is submitted: * * - ng:submit on the form element (add link to ng:submit) * - ng:click on the first button or input field of type submit (input[type=submit]) * * To prevent double execution of the handler, use only one of ng:submit or ng:click. This is * because of the following form submission rules coming from the html spec: * * - If a form has only one input field then hitting enter in this field triggers form submit * (`ng:submit`) * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter * doesn't trigger submit * - if a form has one or more input fields and one or more buttons or input[type=submit] then * hitting enter in any of the input fields will trigger the click handler on the *first* button or * input[type=submit] (`ng:click`) *and* a submit handler on the enclosing form (`ng:submit`) * * @param {string=} name Name of the form. * * @example
text: Required! text = {{text}}
myForm.input.$valid = {{myForm.input.$valid}}
myForm.input.$error = {{myForm.input.$error}}
myForm.$valid = {{myForm.$valid}}
myForm.$error.REQUIRED = {{!!myForm.$error.REQUIRED}}
it('should initialize to model', function() { expect(binding('text')).toEqual('guest'); expect(binding('myForm.input.$valid')).toEqual('true'); }); it('should be invalid if empty', function() { input('text').enter(''); expect(binding('text')).toEqual(''); expect(binding('myForm.input.$valid')).toEqual('false'); });
*/ angularWidget('form', function(form){ this.descend(true); this.directives(true); return ['$formFactory', '$element', function($formFactory, formElement) { var name = formElement.attr('name'), parentForm = $formFactory.forElement(formElement), form = $formFactory(parentForm); formElement.data('$form', form); formElement.bind('submit', function(event) { if (!formElement.attr('action')) event.preventDefault(); }); if (name) { this[name] = form; } watch('valid'); watch('invalid'); function watch(name) { form.$watch('$' + name, function(scope, value) { formElement[value ? 'addClass' : 'removeClass']('ng-' + name); }); } }]; }); angularWidget('ng:form', angularWidget('form'));