Quelle est la signification de require: 'ngModel'?

92

Voici le HTML de ma directive:

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

Dans ma directive, j'ai ceci:

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

Quelqu'un peut-il me dire quelle est la signification de require: 'ngModel'? Je vois cela dans de nombreuses directives différentes. Puis-je appeler cela data-modal?

Je suis confus parce que lorsque je le change en modal de données, je reçois un message d'Angular disant

Controller 'ngModel', required by directive 'textarea', can't be found!
krusty.ar
la source
Partout où vous utilisez cette directive, il devrait y avoir un attribut défini commeng-model='property'
Chandermani
3
Puis-je avoir un modèle data-ng à la place? Aussi pourquoi est-ce que je vois parfois: "require: '? NgModel'," C'est déroutant.

Réponses:

117

L' requireinstruction vous donne le contrôleur de la directive que vous nommez comme quatrième argument de votre linkfonction. (Vous pouvez utiliser ^pour rechercher le contrôleur sur un élément parent; le ?rend facultatif.) require: 'ngModel'Vous donne donc le contrôleur pour la ngModeldirective, qui est unngModelController .

Les contrôleurs de directive peuvent être écrits pour fournir des API que d'autres directives peuvent utiliser; avec ngModelController, vous avez accès à des fonctionnalités spéciales intégrées ngModel, notamment l'obtention et la définition de la valeur. Prenons l'exemple suivant:

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

Cette directive utilise le ngModelcontrôleur pour obtenir et définir la valeur de la couleur à partir du sélecteur de couleurs. Voir cet exemple JSFiddle: http://jsfiddle.net/BinaryMuse/AnMhx/

Si vous utilisez require: 'ngModel', vous ne devriez probablement pas également l'utiliser ngModel: '='dans votre champ d'isolat; le ngModelControllervous donne tous les accès dont vous avez besoin pour modifier la valeur.

L'exemple du bas de la page d'accueil AngularJS utilise également cette fonctionnalité (sauf en utilisant un contrôleur personnalisé, pas ngModel).


En ce qui concerne la casse d'une directive, par exemple, ngModelvs ng-modelvs data-ng-model: alors que Angular prend en charge l'utilisation de plusieurs formulaires sur le DOM, lorsque vous faites référence à une directive par son nom (par exemple, lors de la création d'une directive, ou de l'utilisation require), vous utilisez toujours le lowerCamelCase forme du nom.

Michelle Tilley
la source
2
Y a-t-il une raison particulière require: 'ngModel'à utiliser ngModel: '='?
ErikAGriffin
33

Comme indiqué dans la documentation relative à la création de directives personnalisées : (d'abord à votre question dans le commentaire)

Puis-je avoir un à la data-ng-modelplace?

La réponse:

Bonne pratique : préférez utiliser le format délimité par des tirets (par exemple ng-bindpour ngBind). Si vous souhaitez utiliser un outil de validation HTML, vous pouvez à la place utiliser la dataversion préfixée (par exemple data-ng-bindpour ngBind). Les autres formulaires présentés ci-dessus sont acceptés pour des raisons héritées du passé mais nous vous conseillons de les éviter.

Exemples:

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

Deuxièmement, que ?ngModelreprésente le?

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

Lorsque vous utilisez votre directive, elle la force à être utilisée avec l'attribut / contrôleur ng-model.

Le requiredécor

(Extrait du livre AngularJS de Brad Green & Shyam Seshadri)

D'autres directives peuvent se voir transmettre ce contrôleur avec la syntaxe de la propriété require . La forme complète de require ressemble à:

require: '^?directiveName'

Options:

  1. directiveName

    Ce nom en camel spécifie de quelle directive le contrôleur doit provenir. Donc, si notre <my-menuitem>directive a besoin de trouver un contrôleur sur son parent <my-menu>, nous l'écrirons sous la forme myMenu.

  2. ^

    Par défaut, Angular obtient le contrôleur de la directive nommée sur le même élément. L'ajout de ce ^symbole facultatif indique de remonter également l'arborescence DOM pour trouver la directive. Pour l'exemple, nous aurions besoin d'ajouter ce symbole; la chaîne finale serait ^myMenu.

  3. ?

    Si le contrôleur requis n'est pas trouvé, Angular lancera une exception pour vous informer du problème. L'ajout d'un ?symbole à la chaîne indique que ce contrôleur est facultatif et qu'une exception ne doit pas être levée si elle n'est pas trouvée. Bien que cela semble improbable, si nous voulions laisser <my-menu-item>s être utilisé sans <mymenu>conteneur, nous pourrions l'ajouter pour une chaîne de requête finale de ?^myMenu.

Radim Köhler
la source
21

Les require:'ngModel'et require:'^ngModel'vous permettent d'injecter le modèle attaché à l'élément ou à son élément parent auquel la directive est liée.

C'est fondamentalement le moyen le plus simple de passer ngModel dans la fonction link / compile au lieu de le passer en utilisant une option scope. Une fois que vous avez accès à ngModel, vous pouvez modifier sa valeur en utilisant $setViewValue, le rendre sale / propre en utilisant$formatters , appliquer des observateurs, etc.

Voici un exemple simple pour passer ngModel et changer sa valeur après 5 secondes.

Démo: 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);                
        };
    }
  };
});
codef0rmer
la source