¿Cuál es el significado de require: 'ngModel'?

92

Este es el HTML de mi directiva:

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

En mi directiva tengo esto:

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

¿Alguien puede decirme cuál es el significado de require: 'ngModel'? Veo esto en muchas directivas diferentes. ¿Puedo llamar a este modal de datos?

Estoy confundido porque cuando lo cambio a modal de datos, recibo un mensaje de Angular que dice

Controller 'ngModel', required by directive 'textarea', can't be found!
krusty.ar
fuente
Dondequiera que esté utilizando esta directiva, debe haber un atributo definido comong-model='property'
Chandermani
3
¿Puedo tener un modelo de ng de datos en su lugar? Además, ¿por qué a veces veo: "require: '? NgModel'," Es confuso.

Respuestas:

117

La requireinstrucción le da el controlador para la directiva que nombra como el cuarto argumento de su linkfunción. (Puede usar ^para buscar el controlador en un elemento padre; lo ?hace opcional). Entonces require: 'ngModel'le da el controlador para la ngModeldirectiva, que es unngModelController .

Los controladores de directivas se pueden escribir para proporcionar API que pueden utilizar otras directivas; con ngModelController, obtiene acceso a funciones especiales integradas ngModel, incluida la obtención y el establecimiento del valor. Considere el siguiente ejemplo:

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

Esta directiva usa el ngModelcontrolador para obtener y establecer el valor del color del selector de colores. Vea este ejemplo de JSFiddle: http://jsfiddle.net/BinaryMuse/AnMhx/

Si está usando require: 'ngModel', probablemente no debería usarlo tambiénngModel: '=' en su alcance aislado; el ngModelControllerque da todo el acceso que necesita para cambiar el valor.

El ejemplo inferior en la página de inicio de AngularJS también usa esta funcionalidad (excepto que usa un controlador personalizado, no ngModel).


En cuanto a las mayúsculas y minúsculas de una directiva, por ejemplo, ngModelvs ng-modelvs data-ng-model: mientras que Angular admite el uso de múltiples formularios en el DOM, cuando se refiere a una directiva por su nombre (por ejemplo, al crear una directiva o al usarla require), siempre usa lowerCamelCase forma del nombre.

Michelle Tilley
fuente
2
¿Hay alguna razón en particular por la require: 'ngModel'que deba usarse ngModel: '='?
ErikAGriffin
33

Como se indica en la documentación de Creación de directivas personalizadas : (En primer lugar, a su pregunta en el comentario)

¿Puedo tener una data-ng-modelen su lugar?

La respuesta:

Práctica recomendada: prefiere utilizar el formato delimitado por guiones (por ejemplo, ng-bindpara ngBind). Si desea utilizar una herramienta de validación de HTML, puede utilizar en su lugar la dataversión con prefijo (por ejemplo, data-ng-bindpara ngBind). Los otros formularios que se muestran arriba se aceptan por motivos heredados, pero le recomendamos que los evite.

Ejemplos:

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

En segundo lugar, ¿qué ?ngModelrepresenta?

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

Cuando usa su directiva, obliga a usarla junto con el atributo / controlador ng-model.

El requireescenario

(Extracto del libro AngularJS de Brad Green & Shyam Seshadri)

A otras directivas se les puede pasar este controlador con la sintaxis de propiedad require . La forma completa de require se ve así:

require: '^?directiveName'

Opciones:

  1. directiveName

    Este nombre en forma de camello especifica de qué directiva debe provenir el controlador. Entonces, si nuestra <my-menuitem>directiva necesita encontrar un controlador en su padre <my-menu>, lo escribiríamos como myMenu.

  2. ^

    De forma predeterminada, Angular obtiene el controlador de la directiva nombrada en el mismo elemento. Agregar este ^símbolo opcional dice que también suba por el árbol DOM para encontrar la directiva. Por ejemplo, necesitaríamos agregar este símbolo; la cadena final sería ^myMenu.

  3. ?

    Si no se encuentra el controlador requerido, Angular lanzará una excepción para informarle sobre el problema. Agregar un ?símbolo a la cadena dice que este controlador es opcional y que no se debe lanzar una excepción si no se encuentra. Aunque suena poco probable, si quisiéramos que <my-menu-item>se utilizara s sin un <mymenu>contenedor, podríamos agregar esto para una cadena de requerimiento final de ?^myMenu.

Radim Köhler
fuente
21

El require:'ngModel'y require:'^ngModel'permitir que se inyecte el modelo que se adjunta al elemento o su elemento padre en la que está ligada a la directiva.

Es básicamente una forma más fácil de pasar ngModel a la función de enlace / compilación en lugar de pasarlo usando una opción de alcance. Una vez que tenga acceso a ngModel, puede cambiar su valor usando $setViewValue, ensuciar / limpiar usando $formatters, aplicar observadores, etc.

A continuación se muestra un ejemplo simple para pasar ngModel y cambiar su valor después de 5 segundos.

Demostración: 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
fuente