angular.module.ng.$formFactory

Description

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.

Usage

$formFactory([parentForm]);

Parameters

Returns

{Form}

A new Form instance.

Methods

Properties

Example

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>!';
          }

          HTMLEditorWidget.$inject = ['$element', 'htmlFilter'];
          function HTMLEditorWidget(element, htmlFilter) {
            var self = this;

            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() {
            return ['$formFactory', '$element', function ($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: element}});
              // if the element is destroyed, then we need to notify the form.
              element.bind('$destroy', function() {
                widget.$destroy();
              });
            }];
          });
        </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/);
        });