请求的含义是什么: ‘ ngModel’?

这是我的指令的 HTML:

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

在我的指示中,我这样说:

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

谁能告诉我,需求的意义是什么: ngModel?我在许多不同的指令中都看到了这一点。我能称之为数据模式吗?

我很困惑,因为当我把它改为 data-modal我得到一个消息从角说

Controller 'ngModel', required by directive 'textarea', can't be found!
68518 次浏览

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:

<my-dir></my-dir>
<span my-dir="exp"></span>
<!-- directive: my-dir exp -->
<span class="my-dir: exp;"></span>

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.

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.

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);
};
}
};
});