What's the meaning of require: 'ngModel'?

Angularjs

Angularjs Problem Overview


This is the HTML for my directive:

<textarea data-modal="modal" data-mydir ng:model="abc"></textarea>

In my directive I have this:

return {
  require: 'ngModel',
  replace: true,
  scope: {
    modal: '=modal',
    ngModel: '=',
    pid: '=pid'
  }
}

Can someone tell me, what's the significance of require: ngModel ? I see this in many different directives. Could I call this data-modal?

I am confused because when I change it to data-modal I get a message from Angular saying

Controller 'ngModel', required by directive 'textarea', can't be found!

Angularjs Solutions


Solution 1 - Angularjs

The require instruction gives you the controller for the directive you name as the fourth argument to your link function. (You can use ^ to look for the controller on a parent element; ? makes it optional.) So require: 'ngModel' gives you the controller for the ngModel directive, which is an ngModelController.

Directive controllers can be written to provide APIs that other directives can use; with ngModelController, you get access to special functionality that's built into ngModel, including getting and setting the value. Consider the following example:

<input color-picker ng-model="project.color">

app.directive('colorPicker', function() {
  return {
    require: 'ngModel',
    link: function(scope, element, attrs, ngModel) {
      element.colorPicker({
        // initialize the color to the color on the scope
        pickerDefault: scope.color,
        // update the ngModel whenever we pick a new color
        onColorChange: function(id, newValue) {
          scope.$apply(function() {
            ngModel.$setViewValue(newValue);
          });
        }
      });

      // update the color picker whenever the value on the scope changes
      ngModel.$render = function() {
        element.val(ngModel.$modelValue);
        element.change();                
      };
    }
  }
});

This directive uses the ngModel controller to get and set the value of the color from the colorpicker. See this JSFiddle example: http://jsfiddle.net/BinaryMuse/AnMhx/

If you're using require: 'ngModel', you probably shouldn't also be using ngModel: '=' in your isolate scope; the ngModelController gives you all the access you need to change the value.

The bottom example on the AngularJS homepage also uses this functionality (except using a custom controller, not ngModel).


As for the casing of a directive, for example, ngModel vs ng-model vs data-ng-model: while Angular supports using multiple forms on the DOM, when you refer to a directive by name (for example, when creating a directive, or using require), you always use the lowerCamelCase form of the name.

Solution 2 - Angularjs

As stated in the Creating Custom Directives documentation: (Firstly to your question in the comment)

> Can I have a data-ng-model instead?

The answer:

> Best Practice: Prefer using the dash-delimited format (e.g. ng-bind for ngBind). If you want to use an HTML validating tool, you can instead use the data-prefixed version (e.g. data-ng-bind for ngBind). The other forms shown above are accepted for legacy reasons but we advise you to avoid them.

Examples:

> > > >

Secondly, what does the ?ngModel represent?

// Always use along with an ng-model
require: '?ngModel',

When using your directive, it forces it to be used along with the attribute/controller ng-model.

The require setting

(Extract from the book AngularJS by Brad Green & Shyam Seshadri)

> Other directives can have this controller passed to them with the require property syntax. The full form of require looks like: > > > > > require: '^?directiveName' > > Options: > > 1. directiveName > > This camel-cased name specifies which directive the controller should come from. So if our <my-menuitem> directive needs to find a controller on its parent <my-menu>, we’d write it as myMenu. > > 2. ^ > > By default, Angular gets the controller from the named directive on the same element. Adding this optional ^ symbol says to also walk up the DOM tree to find the directive. For the example, we’d need to add this symbol; the final string would be ^myMenu. > > 3. ? > > If the required controller is not found, Angular will throw an exception to tell you about the problem. Adding a ? symbol to the string says that this controller is optional and that an exception shouldn’t be thrown if not found. Though it sounds unlikely, if we wanted to let <my-menu-item>s be used without a <mymenu> container, we could add this for a final require string of ?^myMenu.

Solution 3 - Angularjs

The require:'ngModel' and require:'^ngModel' allow you to inject the model attached to the element or its parent element on which the directive is bound to.

Its basically an easiest way to pass ngModel into the link/compile function instead passing it using a scope option. Once you have access to ngModel, you can change its value using $setViewValue, make it dirty/clean using $formatters, apply watchers, etc.

Below is a simple example to pass ngModel and change its value after 5 seconds.

Demo: http://jsfiddle.net/t2GAS/2/

myApp.directive('myDirective', function($timeout) {
  return {
    restrict: 'EA',
    require: 'ngModel',
    link: function(scope, element, attrs, ngModel) {
        ngModel.$render = function() {
            $timeout(function() {
                ngModel.$setViewValue('StackOverflow');  
            }, 5000);                
        };
    }
  };
});

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1943020View Question on Stackoverflow
Solution 1 - AngularjsMichelle TilleyView Answer on Stackoverflow
Solution 2 - AngularjsRadim KöhlerView Answer on Stackoverflow
Solution 3 - Angularjscodef0rmerView Answer on Stackoverflow