ngModel is a directive which binds input, select and textarea, and stores the required user value in a variable and we can use that variable whenever we require that value. It also is used during validations in a form.
With the ng-model directive you can bind the value of an input field to a variable created in Angular. The binding goes both ways. If the user changes the value inside the input field, the Angular property will also change its value. The ngmodel directive is not part of the Angular Core library.
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.
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
forngBind
). If you want to use an HTML validating tool, you can instead use thedata
-prefixed version (e.g.data-ng-bind
forngBind
). 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
.
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:
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.
^
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
.
?
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:'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);
};
}
};
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With