Что означает require: 'ngModel'?

92

Это HTML-код моей директивы:

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

В моей директиве есть это:

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

Может кто-нибудь сказать мне, какое значение имеет require: 'ngModel'? Я вижу это во многих разных директивах. Могу я назвать это модальным для данных?

Я смущен, потому что когда я меняю его на модальный, я получаю сообщение от Angular, говорящее

Controller 'ngModel', required by directive 'textarea', can't be found!
krusty.ar
источник
Где бы вы ни использовали эту директиву, должен быть атрибут, определенный какng-model='property'
Chandermani
3
Можно ли вместо этого использовать модель data-ng? Также почему я иногда вижу: "require: '? NgModel'," Это сбивает с толку.

Ответы:

117

requireИнструкция дает контроллер для директивы вы назвать в качестве четвертого аргумента вашей linkфункции. (Вы можете использовать ^для поиска контроллера в родительском элементе; ?делает его необязательным.) Таким образом, require: 'ngModel'вы получаете контроллер для ngModelдирективы, которым являетсяngModelController .

Контроллеры директив могут быть написаны для предоставления API, которые могут использовать другие директивы; с помощью ngModelController, вы получаете доступ к специальным встроенным функциям ngModel, включая получение и установку значения. Рассмотрим следующий пример:

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

Эта директива использует ngModelконтроллер для получения и установки значения цвета из палитры цветов. См. Этот пример JSFiddle: http://jsfiddle.net/BinaryMuse/AnMhx/

Если вы используете require: 'ngModel', вам, вероятно, также не следует использовать ngModel: '='в своей изолированной области; ngModelControllerдает вам все доступа вам необходимо изменить значение.

Нижний пример на домашней странице AngularJS также использует эту функциональность (за исключением использования настраиваемого контроллера ngModel).


Что касается корпуса директивы, например ngModelvs ng-modelvs data-ng-model: в то время как Angular поддерживает использование нескольких форм в DOM, когда вы ссылаетесь на директиву по имени (например, при создании директивы или использовании require), вы всегда используете lowerCamelCase форма имени.

Мишель Тилли
источник
2
Есть ли особая причина, по которой require: 'ngModel'следует использовать ngModel: '='?
ErikAGriffin
33

Как указано в документации по созданию пользовательских директив : (во-первых, на ваш вопрос в комментарии)

Можно мне data-ng-modelвзамен?

Ответ:

Рекомендация : предпочитайте использовать формат с разделителями тире (например, ng-bindдля ngBind). Если вы хотите использовать инструмент проверки HTML, вы можете вместо этого использовать dataверсию с префиксом (например, data-ng-bindдля ngBind). Остальные формы, показанные выше, принимаются по причинам, связанным с устареванием, но мы советуем вам их избегать.

Примеры:

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

Во-вторых, что собой ?ngModelпредставляет?

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

При использовании вашей директивы он заставляет использовать ее вместе с атрибутом / контроллером ng-model.

requireустановка

(Отрывок из книги AngularJS Брэда Грина и Шьяма Сешадри)

В других директивах этот контроллер может быть передан им с синтаксисом свойства require . Полная форма require выглядит так:

require: '^?directiveName'

Параметры:

  1. directiveName

    Это имя в верблюжьем регистре указывает, из какой директивы должен исходить контроллер. Поэтому, если нашей <my-menuitem>директиве нужно найти контроллер на своем родительском <my-menu>элементе, мы должны написать его как myMenu.

  2. ^

    По умолчанию Angular получает контроллер из указанной директивы того же элемента. Добавление этого необязательного ^символа означает также, что нужно пройти вверх по дереву DOM, чтобы найти директиву. Для примера нам нужно добавить этот символ; последняя строка будет ^myMenu.

  3. ?

    Если требуемый контроллер не найден, Angular выдаст исключение, чтобы сообщить вам о проблеме. Добавление ?символа в строку означает, что этот контроллер является необязательным и что исключение не должно генерироваться, если оно не найдено. Хотя это звучит маловероятно, если бы мы хотели <my-menu-item>использовать s без <mymenu>контейнера, мы могли бы добавить это в последнюю строку require типа ?^myMenu.

Радим Кёлер
источник
21

Они require:'ngModel'и require:'^ngModel'позволяют вам внедрить модель, прикрепленную к элементу или его родительскому элементу, к которому привязана директива.

По сути, это самый простой способ передать ngModel в функцию ссылки / компиляции вместо того, чтобы передавать его с помощью параметра области. Получив доступ к ngModel, вы можете изменить его значение с помощью $setViewValue, сделать его грязным / чистым с помощью $formatters, применить наблюдателей и т. Д.

Ниже приведен простой пример передачи ngModel и изменения его значения через 5 секунд.

Демо: 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
источник