Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Question Mark in Directive Require

I was following a tutorial trying to get a directive to work that required ngModel:

app.directive("contenteditable", function() {
    return {
        restrict: "A",
        require: "ngModel",
        /* etc. */

This failed to load saying:

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

Looking at similar code in the angular docs, I changed the require line:

require: "?ngModel"

Now it works fine. I'm guessing that the ? makes it optional but that doesn't make much sense to me. What is the question mark doing and (if it's not obvious) why is it allowing the directive to work?

like image 576
jcuenod Avatar asked Apr 21 '15 15:04

jcuenod


People also ask

What is @? In Angular directive scope?

These prefixes are used to bind the parent scope's methods and properties to the directive scope. There are 3 types of prefixes in AngularJS: '@' – Text binding / one-way binding. '=' – Direct model binding / two-way binding.

What is the use of question mark in Angular?

In some code snippets, you may have seen that Angular expressions have a question mark after them. Angular refers to it as 'Safe Navigation Operator'. It makes sure that we are not seeing null and undefined values in our application when we want to access properties of an object.

What is =? In AngularJS?

Locals definition is a hash of local scope property to its source: = or =attr - set up bi-directional binding between a local scope property and the parent scope property of name defined via the value of the attr attribute.

How are attributes marked in AngularJS?

AngularJS directives are extended HTML attributes with the prefix ng- . The ng-app directive initializes an AngularJS application. The ng-init directive initializes application data. The ng-model directive binds the value of HTML controls (input, select, textarea) to application data.


3 Answers

Just to add more details for @Igor Pantovic answer about ^ prefix from AngularJS $compile guide:

  • (no prefix) - Locate the required controller on the current element. Throw an error if not found.

  • ? - Attempt to locate the required controller or pass null to the link fn if not found.

  • ^ - Locate the required controller by searching the element and its parents. Throw an error if not found.

  • ^^ - Locate the required controller by searching the element's parents. Throw an error if not found.

  • ?^ - Attempt to locate the required controller by searching the element and its parents or pass null to the link fn if not found.

  • ?^^ - Attempt to locate the required controller by searching the element's parents, or pass null to the link fn if not found.

like image 24
Yauhen Avatar answered Oct 03 '22 22:10

Yauhen


It's exactly what you guessed: ? makes a directive optional.

Basically, these are at your disposal when defining directive requirements:

  1. someDirective : Require someDirective on same element and pass it to linking function
  2. ?someDirective : Pass someDirective controller if available on same element to linking function. If not, pass null.
  3. ^someDirective : Require someDirective on one of the parent elements and pass it to linking function.
  4. ?^someDirective : Pass someDirective controller if available on one of parent elements to linking function. If not, pass null.

If your directive requires multiple other directives, you can use the same thing but pass an array like so:

require: ['firstRequiredDirective', '^secondRequiredDirective'] 

This time, you will get an array of required directive's controllers passed to your linking function.

In your case, if element having your contenteditable directive has ngModel, ngModelController will get passed to your linking function.

If there is no ngModel directive on it, it will pass null.

like image 143
Igor Pantović Avatar answered Oct 04 '22 00:10

Igor Pantović


You are correct that ? makes the required directive optional. Meaning that null will be returned in the link function of the directive for that requirement. The way you are using it states that ngModel maybe on the same element as contenteditable but it is not actually required.

like image 28
Enzey Avatar answered Oct 04 '22 00:10

Enzey