Use $formFactory
to create a new instance of a form
controller or to find the nearest form instance for a given DOM element.
The form instance is a collection of widgets, and is responsible for life cycle and validation of widget.
Keep in mind that both form and widget instances are scopes
.
$formFactory([parentForm]);
parentForm(optional) – {Form} –
The form which should be the parent form of the new form controller.
If none specified default to the rootForm
.
{Form}
– A new form instance.
Static method on $formFactory
service.
Retrieve the closest form for a given element or defaults to the root
form. Used by the
form
element.
element – {Element} –
The element where the search for form should initiate.
Property of the form and widget instance.
Summary of all of the errors on the page. If a widget emits $invalid
with REQUIRED
key,
then the $error
object will have a REQUIRED
key with an array of widgets which have
emitted this key. form.$error.REQUIRED == [ widget ]
.
Property of the form and widget instance.
True if any of the widgets of the form are invalid.
Property of the form and widget instance.
True if all of the widgets of the form are valid.
Static property on $formFactory
Each application (root scope) gets a root form which is the top-level parent of all forms.
Upon receiving the $invalid
event from the widget update the $error
, $valid
and $invalid
properties of both the widget as well as the from.
validationKey – {String} –
The validation key to be used when updating the $error
object.
The validation key is what will allow the template to bind to a specific validation error
such as <div ng:show="form.$error.KEY">error for key</div>
.
Upon receiving the $valid
event from the widget update the $error
, $valid
and $invalid
properties of both the widget as well as the from.
validationKey – {String} –
The validation key to be used when updating the $error
object.
The validation key is what will allow the template to bind to a specific validation error
such as <div ng:show="form.$error.KEY">error for key</div>
.
Emit the $validate
event on the widget, giving a widget a chance to emit a
$valid
/ $invalid
event base on its state. The $validate
event is triggered when the
model or the view changes.
A widget is responsible for emitting this event whenever the view changes do to user interaction.
The event takes a $viewValue
parameter, which is the new value of the view. This
event triggers a call to $parseView()
as well as $validate
event on widget.
viewValue – {*} –
The new value for the view which will be assigned to widget.$viewValue
.
This example shows how one could write a widget which would enable data-binding on
contenteditable
feature of HTML.
<script> function EditorCntl() { this.html = '<b>Hello</b> <i>World</i>!'; } function HTMLEditorWidget(element) { var self = this; var htmlFilter = angular.filter('html'); this.$parseModel = function() { // need to protect for script injection try { this.$viewValue = htmlFilter(this.$modelValue || '').get(); if (this.$error.HTML) { // we were invalid, but now we are OK. this.$emit('$valid', 'HTML'); } } catch (e) { // if HTML not parsable invalidate form. this.$emit('$invalid', 'HTML'); } } this.$render = function() { element.html(this.$viewValue); } element.bind('keyup', function() { self.$apply(function() { self.$emit('$viewChange', element.html()); }); }); } angular.directive('ng:contenteditable', function() { function linkFn($formFactory, element) { var exp = element.attr('ng:contenteditable'), form = $formFactory.forElement(element), widget; element.attr('contentEditable', true); widget = form.$createWidget({ scope: this, model: exp, controller: HTMLEditorWidget, controllerArgs: [element]}); // if the element is destroyed, then we need to notify the form. element.bind('$destroy', function() { widget.$destroy(); }); } linkFn.$inject = ['$formFactory']; return linkFn; }); </script> <form name='editorForm' ng:controller="EditorCntl"> <div ng:contenteditable="html"></div> <hr/> HTML: <br/> <textarea ng:model="html" cols=80></textarea> <hr/> <pre>editorForm = {{editorForm}}</pre> </form>
it('should enter invalid HTML', function() { expect(element('form[name=editorForm]').prop('className')).toMatch(/ng-valid/); input('html').enter('<'); expect(element('form[name=editorForm]').prop('className')).toMatch(/ng-invalid/); });