Improve this doc  View Source

ngModel.NgModelController

  1. - type in module ng

NgModelController provides API for the ng-model directive. The controller contains services for data-binding, validation, CSS updates, and value formatting and parsing. It purposefully does not contain any logic which deals with DOM rendering or listening to DOM events. Such DOM related logic should be provided by other directives which make use of NgModelController for data-binding.

Custom Control Example

This example shows how to use NgModelController with a custom control to achieve data-binding. Notice how different directives (contenteditable, ng-model, and required) collaborate together to achieve the desired result.

Note that contenteditable is an HTML5 attribute, which tells the browser to let the element contents be edited in place by the user. This will not work on older browsers.

  Edit in Plunker
[contenteditable] {
  border: 1px solid black;
  background-color: white;
  min-height: 20px;
}

.ng-invalid {
  border: 1px solid red;
}
angular.module('customControl', []).
  directive('contenteditable', function() {
    return {
      restrict: 'A', // only activate on element attribute
      require: '?ngModel', // get a hold of NgModelController
      link: function(scope, element, attrs, ngModel) {
        if(!ngModel) return; // do nothing if no ng-model

        // Specify how UI should be updated
        ngModel.$render = function() {
          element.html(ngModel.$viewValue || '');
        };

        // Listen for change events to enable binding
        element.on('blur keyup change', function() {
          scope.$apply(read);
        });
        read(); // initialize

        // Write data to the model
        function read() {
          var html = element.html();
          // When we clear the content editable the browser leaves a <br> behind
          // If strip-br attribute is provided then we strip this out
          if( attrs.stripBr && html == '<br>' ) {
            html = '';
          }
          ngModel.$setViewValue(html);
        }
      }
    };
  });
<form name="myForm">
 <div contenteditable
      name="myWidget" ng-model="userContent"
      strip-br="true"
      required>Change me!</div>
  <span ng-show="myForm.myWidget.$error.required">Required!</span>
 <hr>
 <textarea ng-model="userContent"></textarea>
</form>
it('should data-bind and become invalid', function() {
if (browser.params.browser == 'safari' || browser.params.browser == 'firefox') {
  // SafariDriver can't handle contenteditable
  // and Firefox driver can't clear contenteditables very well
  return;
}
var contentEditable = element(by.css('[contenteditable]'));
var content = 'Change me!';

expect(contentEditable.getText()).toEqual(content);

contentEditable.clear();
contentEditable.sendKeys(protractor.Key.BACK_SPACE);
expect(contentEditable.getText()).toEqual('');
expect(contentEditable.getAttribute('class')).toMatch(/ng-invalid-required/);
});

Methods

Properties