AngularJS. Директивы и модули


Содержание материала:

AngularJS Hello world example. Основы AngularJS: модуль, контроллер, выражения

Angular JS Hello world example. Основы Angular JS . Подключение и настройка фреймворка. Понятия приложения, модуля, контроллера и выражений в Angular JS .

Обзор приложения Spring MVC + AngularJS + Bootstrap + HTML5
Используемые технологии и библиотеки
  • Spring MVC 4.2.4.Release
  • AngularJS 1.5.0
  • IntelliJ IDEA 15.0.2

1. Описание задачи

Познакомиться с фреймворком Angular JS — написать простую Hello World jsp страницу с использованием возможностей Angular JS . Подключить angular.js , ознакомиться с понятиями контроллера ( ng-controller ), приложения ( ng-app ), модуля ( angular.module ). Рассмотреть применение выражений ( expressions ).

2. Структура проекта

В веб ресурсах добавлен пакет resources\angularjs с js файлами angular. Рассматриваемые в статье понятия написаны в пакете view\angularjs ( expressions.jsp ). angularindex.jsp — содержание доступных тем по Angular JS .

3. Описание AngularJS

  • Angular JS на 100% написанный на JavaScript client s >JS можно запускать как на мобильных так и на стационарный устройствах
  • Использует концепцию MVC (models, views, controllers)
  • Предоставляет удобный для сопровождения и юнит тестирования код
  • Использует Dependency Injection (DI) принцип для внедрения зависимостей компонентов
  • Расширяет HTML DOM модель с помощью добавления атрибутов к HTML тэгам
  • Позволяет создавать пользовательские интерфейсы с широкими возможностями
  • Официально поддерживается компанией Google
  • Использует квадратные скобки с префиксом ng (отсылка к Angular)
3.1 Архитектура AngularJS
3.1.1. Модуль AngularJS

Приложение Angular состоит из модулей. В модуль могут входить другие модули. Таким образом вы можете считать модуль контейнером для различных частей вашего приложения. Каждый модуль состоит из сервисов, контроллеров, директив, провайдеров и шаблонов.

  • angular.module — глобальное определение модуля. Все модули, которые должны быть доступны в приложении должны регистрироваться с помощью этого механизма.
  • applicationName — имя модуля.
  • [ ] — здесь перечисляются зависимости для этого модуля (например сторонние библиотеки).
  • ng-app=’applicationName’ — когда HTML документ будет загружаться, то на этом месте будет запущен модуль с именем applicationName и далее будет вызван фильтр с именем greet . В результате увидим надпись Hello, World!.

Сообщество AngularJS рекомендует разбивать приложение на модули по следующему принципу:

  • Модуль для каждой функции (в смысле части бизнес логики приложения, а не имени функции JS кода).
  • Модуль для каждого повторно используемого компонента (особенно для директив и фильтров).
  • Модуль для уровня приложения, который содержит зависимости для вышестоящих модулей и включает код инициализации.
3.1.2. Контроллер AngularJS

Контроллер — компонент, который используется для осуществления взаимодействия между сервисами. Сервис — компонент, который используется для связи частей приложения (например сервис для доступа к данным и т.д.). В Angular контроллеры определяются с помощью конструктора JavaScript, в который передается сервис $scope .

Здесь мы задали контроллер для модуля myApp с именем GreetingController с помощью метода controller() . Далее с помощью внедрения зависимостей (Dependency Injection) определили свойство greeting с значением Preved, medved! .

Контроллер присоединяется к DOM с помощью директивы ng-controller .

Контроллеры необходимо использовать для:

  • Инициализации объекта $scope .
  • Добавления поведения к объекту $scope .

Контроллер не следует использовать для:

  • Манипуляцией DOM. Контроллеры должны содержать только бизнес логику. В ангуляре есть директивы и связывание данных для манипуляции с DOM.
  • Ввода данных — для этого есть отдельные элементы для управления формами.
  • Фильтрации вывода — для этого есть фильтры AngularJS.
  • Открытие доступа к участкам кода или состоянием между контроллерами — для этого используются сервисы Angular.
  • Управлением жизненным циклом других компонентов (например для создания экземпляра сервиса).
3.1.3. $scope

Scope — объект, который ссылается на модель приложения. Этот объект является контекстом для выполнения выражений или обработки событий. Scope объекты имеют иерархию. Обычно, когда вы создаете приложение, то вам необходимо установить начальное состояние для объекта AngularJS $scope . В предыдущем примере установка состояния для $scope осуществлялась путем присоединения свойства greetings к объекту $scope ( $scope.greeting = ‘…’ ). Объект $scope — определяет область видимости для каких-либо свойств.

В общем к характеристикам объектов $scope относят:

Общение директив между собой в AngularJS

Сегодня мы поговорим о такой опции директив, как require. Понимание данного функционала AngularJS не входит в базовый уровень знаний, который требуется для разработки простых приложений, поэтому у многих вызывает кучу вопросов.

Очень часто при написании директив возникает необходимость в их взаимодействии, общении, чтоб одна из них могла, например, вызвать метод добавления нового элемента в массиве у другой. В AngularJS есть для этого готовый механизм, который мы сейчас и рассмотрим.

Ну что же, приступим к написанию нашего приложения, которое прояснит нам смысл этой загадочной опции require:

В этом коде мы видим директиву developer со своим контроллером, который будет использоваться в качестве API (Application Programming Interface) при взаимодействии с другими директивами. Суть директивы developer проста — при наведении на элемент в консоль выводится список навыков разработчика.

Далее, мы добавим следующий код, который создаёт ещё одну директиву внутри приложения для взаимодействия с директивой developer.

Как видно из кода, у директивы есть свойство require, которое делает инъекцию контроллера, расположенного в другой директиве developer, в link-функцию создаваемой путём добавления параметра функции (здесь это developerCtrl).

Надо заметить, что у этого параметра, запрашивающего контроллер, нет требований и соглашений по именованию.

Создадим ещё две директивы — «html» и «angularjs»:

Теперь каждая из этих директив связана с внешними API-методами контроллера директивы developer.

Мы можем изменить нашу разметку, добавив новые навыки нашему разработчику:

Как и предполагалось, отдельные директивы взаимодействуют с контроллером директивы элемента.

Изолированная область видимости

Но не всё так хорошо, как нам кажется! Давайте создадим несколько экземпляров директивы developer:

Несмотря на то, что у каждой из них свой набор дополняющих директив, каждый экземпляр обрабатывается последовательно. И поскольку область видимости у этих двух элементов с директивой developer общая, и инициализация каждой из них перезаписывает значение предыдущей, мы получаем следствие — на какой бы элемент мы не навели курсор, получим значения от последней директивы.

Решением данной проблемы будет создание изолированной области видимости для директивы developer. Давайте так и сделаем:

Вы можете посмотреть на полный код нашего приложения:

Общение с вышерасположенной директивой

В примерах выше происходило общение директив одного DOM-элемента (в нашем случае элемент developer). Но в некоторых случаях есть необходимость во взаимодействии между директивами на разных уровнях. Например, нижележащий элемент что-то делает с вышестоящим. На этот случай также есть готовое решение внутри фрэймворка. Для этого достаточно добавить в значение опции require префикс «^» («циркумфлекс» или «крышечка» в простонародье). Этот префикс означает, что директива будет искать контроллер на своем элементе или на элементах, расположенных выше.
Посмотрите на изменение кода в нашем приложении. Тут показано на примере общение вложенной директивы и расположенной на том же элементе:

Маленькое дополнение

Теперь, когда мы знаем, для чего нужна опция require, будет приятно узнать, что она может принимать в качестве значения несколько параметров, т.е. общение может происходить с несколькими директивами одновременно. В таком случае мы получим в функцию link вызывающей директивы не контроллер, а массив контроллеров. Пример:

И ещё, хотелось бы с тобой поделиться советом из документации AngularJS по написанию директив. Кто-то из вас может спросить, в чём разница опции controller и link у директив? Основное различие в том, что контроллер может выставлять некий API наружу. Отсюда вывод, который относится к категории «Best Practices»: используйте опцию controller, если вы хотите дать API для других директив. В других случаях используйте функцию link.

Заключение

Ну что же? Я очень надеюсь, что эта статья тебе понравилась, и ты стал лучше понимать междирективное взаимодействие в AngularJS. Используя этот метод можно решить многие нетривиальные задачи, возникающие при разработке клиентского приложения. Не забудь поделиться ссылкой со всеми интересующимися!

Создание пользовательских директив в AngularJS. Часть I — Основы.

Статья является переводом замечательного цикла статей от Дэна Вахлина (Dan Wahlin) . Надеюсь она принесет вам пользу.

AngularJS обеспечивает вас множеством директив, которые вы можете использовать для манипуляции с DOM, роутингом, событиями и функциями обработчиков событий, привязкой данных, асоциацией контроллеров и области видимости и многое другое. Директивы, такие как ng-click, ng-show/ng-hide, ng-repeat и многие другие упрощают начало работы с фреймворком на первых этапах.

Хотя встроенные директивы охватывают множество различных сценариев, могут быть случаи, когда вам придется написать собственные и вам придется задаться вопросом как это сделать. В этой серии постов мы шаг за шагом рассмотрим как работают директивы и как написать свои собственные. Общая цель заключается в том, чтобы делать простые, легковесные примеры директив, которые будут прогрессировать от урока к уроку.

Я предполагаю, что вы уже знаете, что такое директивы и как они используются. Если вы новичок, то вы можете посмотреть AngularJS в 60 минут на Youtube (или получить электронную версию книги) или посмотрите курс AngularJS быстрый старт.

Написание собственных директив это просто, верно?

Директивы AngularJS могут быть немного пугающими, когда вы видите их первый раз( а это так и есть, прим. переводчика). Они предлагают множество различных настроек, имеют несколько загадочных особенностей (загадочный это мой политически корректный термин для “о чем они думали здесь?”). Они кажутся сложными на первый взгляд, однако, как только вы понимаете как эти части сочетаются друг с другом все становится не так уж и плохо. Я сравниваю это с обучением игры на музыкальном инструменте (много воды не по теме, но что же делать, прим. переводчика). Первый раз, когда вы играете на фортепиано или гитаре, вы чувствуете себя совершенно не компетентным, тем не менее, после практических занятий ваши навыки становятся лучше и вы можете играть более современную музыку (и вам за это не стыдно, прим. переводчика). Тоже самое с директивами — они требуют немного практики, но с помощью них вы можете делать мощные вещи. Я с нетерпением жду того дня, когда Polymer и Web-components заменят нам директивы, которые мы пишем сегодня. Пройдите по ссылкам и загляните в будущее веба.


На данный момент Polymer и веб компоненты полностью поддерживаются только в Webkit (Январь 2015) и имеют достаточное количество багов. Прим. переводчика.

Введение в Пользовательские Директивы

Почему вы должны захотеть писать пользовательские директивы? Давайте предположим, что вы озадачены конвертированием коллекции покупателей в некую таблицу (сетку), которая должна отображаться в представлении (view). Можно добавить функционал в DOM и контроллер обработает его, однако это усложнит тестирование контроллера и сломает MVC подход, когда контроллер будет отвечать на отображение. Вы не должны хотеть делать такие вещи в AngularJS приложении. Такой тип функциональности должен находится в директиве. В другом случае у вас есть привязки данных, которые вы хотите использовать во многих представлениях, а также использовать их повторно. Некий компонент может быть загружен через ng-include (об этом чуть позже) и директива должна работать в этом сценарии несмотря ни на что. Есть множество способов того, как пользовательские директивы могут работать, этот маленький пример выше всего лишь вершина айсберга.

Давайте начнем с очень простой директивы. Предположим, что мы имеем следующий модуль и контроллер, определенный в приложении (я буду ссылаться на этот модуль и контроллер в будущих постах).

Давайте предположим, что мы выводим данное выражение снова и снова исходя из данных приложения

Одна из техник, при которой мы можем переиспользовать шаблон связывания данных в потомках представления (я назвал их myChildView.html) это вызвать в родителе ng-include и сослаться на наш шаблон myChildView.html.

Пока эта работа завершена, давайте посмотрим на другую технику, которая также может быть использована для связывания данных выражения в пользовательской директиве. Чтобы создать директиву, вы в первую очередь должны расположить указать модуль директивы, далее нужно вызвать ее directive() функцию. Данная функция принимает имя директивы как функции. Вот пример нашей директивы со связыванием данных.

Является ли это решение более дорогим по отношению к к ng-include? Не сейчас. Однако директивы могут сделать больше с меньшим количеством кода. Пример ниже показывает связывание директивы mySharedScope с

Когда директива будет запущена, она выведет следующие данные, которые контроллер показал нам ранее

Топ-пост этого месяца:  Использование переменных в kama_thumb_src

Name: David
Street: 1234 Anywhere St.

Первая вещь, которую нужно запомнить, это то, что mySharedScope ссылается на view используя my-shared-scope. Почему так? Ответ в том, что имена директивы определены в нижнемВерблюжьемСинтаксисе. Для примера, когда вы используете ngRepeat директиву, вы используете ng-repeat версию в DOM узле.

Другая интересная вещь в директиве в том, что она наследует область видимости (scope) от своего представления (view) по умолчанию. Если контроллер, показанный ранее, (CustomerController) связан с областью видимости, то свойство $scope от кастомера доступено и в директиве. Это называется общей областью видимости. Общая область видимости прекрасно работает, если вы многое знаете о родительсткой области видимости. В ситуациях, когда вы хотите переиспользовать директиву, вы не можете полагаться на знания свойств в области видимости и это называют изолированной областью видимости. Более подробное описание изолированной области видимости я приведу в следующем посте.

Свойства Директив

В предыдущем mySharedScope директиве одно единственное свойство было названо template и было определено в объекте литерала возвращенной из функции. Это свойство отвечает за определение кода шаблона директивы (выражение привязки данных в этом случае), и генерацию HTML когда шаблона. Какие свойства становятся нам доступны?

Пользовательские директивы, как правило, возвращают литерал объекта, который отвечает за определение свойства необходимое директиве, такое как шаблон, контроллер (если используется), DOM манипуляции и многое другое. Могут быть использованы несколько различных свойств (полный список здесь). Вот пример того, как выгледят несколько ключевых свойств, которые вы можете встретить и пример их использования.

Короткое описание каждого свойства ниже:

restrict — Determines where a directive can be used (as an element, attribute, CSS class, or comment).

scope — Used to create a new child scope or an isolate scope.

template — Defines the content that should be output from the directive. Can include HTML, data binding expressions, and even other directives.

template — UrlProvides the path to the template that should be used by the directive. It can optionally contain a DOM element id when templates are defined in

Освоение директив AngularJS

Russian (Pусский) translation by Ilya Nikov (you can also view the original English article)

Директивы являются одним из самых мощных компонентов AngularJS, помогая вам расширять основные элементы/атрибуты HTML и создавать многоразовые и тестируемые компоненты. В этом уроке я покажу вам, как использовать директивы AngularJS с лучшими практиками из реальной жизни.

То, что я имею в виду здесь во время учебника под директивам, — это в основном пользовательские директивы. Я не буду пытаться научить вас, как использовать встроенные директивы, такие как ng-repeat , ng-show и т.д. Я покажу вам, как использовать пользовательские директивы для создания ваших собственных компонентов.

  1. Простые директивы
  2. Ограничения директивы
  3. Изолированная область видимости
  4. Области видимости директив
  5. Наследование директивы
  6. Отладка директивы
  7. Тестирование директивы
  8. Тестирование области видимости
  9. Вывод

1. Простые директивы

Скажем, у вас есть приложение электронной коммерции о книгах, и вы показываете конкретные детали книги в нескольких областях, таких как комментарии, страницы профиля пользователя, статьи и т.д. Виджет вашей книги может выглядеть следующим образом:

В этом виджете есть изображение книги, название, описание, комментарии и рейтинг. Сбор этой информации и включение определенного элемента dom могут быть трудными в каждом месте, которое вы хотите использовать. Давайте превратим это представление в виджет, используя директиву AngularJS.

В приведенном выше примере функция directive была использована для создания директивы. Название директивы — book . Эта директива возвращает объект, и давайте немного поговорим об этом объекте. restrict — это определение типа директивы, и оно может быть A (Attribute), C (class), E (Element) и M (coMment). Вы можете видеть использование каждого из них соответственно ниже.

scope предназначена для управления областью действия директивы. В приведенном выше случае данные книги передаются в шаблон директивы с использованием типа области « = ». В следующих разделах я подробно расскажу о области применения. templateUrl используется для вызова представления для рендеринга определенного контента с использованием данных, переданных в область действия директивы. Вы также можете использовать template и предоставить HTML-код напрямую, например:

В нашем случае у нас сложная структура HTML, и именно поэтому я выбрал параметр templateUrl .

2. Ограничения директивы

Директивы определены в файле JavaScript вашего проекта AngularJS и используются на странице HTML. Можно использовать директивы AngularJS на HTML-страницах следующим образом:

A (Attribute)

В этом использовании имя директивы используется внутри стандартных элементов HTML. Скажем, у вас есть ролевое меню в вашем приложении электронной коммерции. Это меню сформировано в соответствии с вашей текущей ролью. Вы можете определить директиву, чтобы определить, должно ли отображаться текущее меню или нет. Ваше меню HTML может выглядеть следующим образом:

а директива следующим образом:

Если вы используете restricted директиву в элементе меню в качестве атрибута, вы можете выполнить проверку уровня доступа для каждого меню. Если текущий пользователь не авторизовался, это конкретное меню не будет отображаться.

Итак, что это за функция link ? Все просто, функция link — это функция, которую вы можете использовать для выполнения операций, ориентированных на конкретные действия. Директива не только дает некоторый HTML-код, предоставляя некоторые входы. Вы также можете связывать функции с элементом директивы, вызывать службу и обновлять значение директивы, получать директивные атрибуты, если это директива типа E и т.д.

C (Class)

Вы можете использовать имя директивы внутри классов элемента HTML. Предполагая, что вы будете использовать указанную выше директиву как C , вы можете обновить restrict директивы как C и использовать ее следующим образом:

У каждого элемента уже есть класс для стилизации, и по мере добавления класса restricted он фактически является директивой.

E (Element)

Вам не нужно использовать директиву внутри элемента HTML. Вы можете создать свой собственный элемент, используя директиву AngularJS с ограничением E . Предположим, что у вас есть пользовательский виджет в вашем приложении, чтобы показывать в нескольких местах вашего приложения username , avatar и reputation . Вы можете использовать такую директиву:

Код HTML будет следующим:

В приведенном выше примере создается пользовательский элемент, и некоторые атрибуты предоставляются как username , avatar и reputation . Я хочу обратить внимание на тело функции link. Атрибуты элемента присваиваются области действия. Первым параметром функции связи является область действия текущей директивы. Третьим параметром директивы является объект атрибута директивы, а это означает, что вы можете прочитать любой атрибут из пользовательской директивы, используя attrs.attr_name . Значения атрибутов присваиваются области действия, поэтому они используются внутри шаблона.

Фактически, вы можете сделать эту операцию короче, и я расскажу об этом позже. Этот пример предназначен для понимания основной идеи использования.

M (coMment)

Это использование не очень распространено, но я покажу, как его использовать. Допустим, вам нужна форма комментариев для вашего приложения для использования ее во многих местах. Вы можете сделать это, используя следующую директиву:

И в элементе HTML:

3. Изолированная область действия

Каждая директива имеет свою собственную область действия, но вам нужно быть осторожным с привязкой данных к объявлению директивы. Скажем, что вы реализуете часть basket своего приложения для электронной коммерции. На странице корзины у вас есть элементы, уже добавленные здесь раньше. Каждый предмет имеет поле количества, чтобы выбрать, сколько предметов вы хотите купить, например:

Вот объявление директивы:

И для отображения трех элементов в HTML:

Проблема здесь в том, что всякий раз, когда вы выберете количество требуемого элемента, все разделы количества элементов будут обновлены. Почему? Потому что есть двусторонняя привязка данных с именем count , но область не изолирована. Чтобы выделить область действия, просто добавьте scope: <> в атрибут директивы в разделе return:

Это приведет к тому, что ваша директива будет иметь свою собственную изолированную область, поэтому двусторонняя привязка данных будет происходить внутри этой директивы отдельно. Я также расскажу об атрибуте scope чуть позже.

4. Области директив

Основным преимуществом директивы является то, что это многоразовый компонент, который можно использовать легко — вы даже можете предоставить некоторые дополнительные атрибуты этой директивы. Но как можно передать дополнительное значение, привязку или выражение в директиву, чтобы данные могли использоваться внутри директивы?

«@» Scope: этот тип области используется для передачи значения в область действия директивы. Предположим, что вы хотите создать виджет для уведомления:

И вы можете использовать:

В этом примере значение сообщения просто присваивается области действия директивы. Отображаемый HTML-контент будет выглядеть следующим образом:

«=» Scope: В этом типе области переменные области пропускаются вместо значений, что означает, что мы не будем передавать <> , вместо этого мы передадим message . Причиной этой функции является создание двусторонней привязки данных между директивой и элементами страницы или контроллерами. Давайте посмотрим на это в действии.

В этой директиве мы пытаемся создать виджет для отображения ввода текста комментария, чтобы сделать комментарий для конкретной книги. Как вы можете видеть, эта директива требует, чтобы один атрибут text создавал двустороннюю привязку данных между другими элементами на страницах. Вы можете использовать это на странице:

Это просто покажет текстовое поле на странице, поэтому давайте добавим что-то большее, чтобы взаимодействовать с этой директивой:

Всякий раз, когда вы вводите текст в первом текстовом поле, он также вводится во втором текстовом поле. Вы можете сделать это наоборот. В директиве мы передали переменную scope commentText вместо значения, и эта переменная является ссылкой на привязку данных к первому текстовому полю.

«&» Scope: мы можем передать значение и ссылку. В этом виде области мы рассмотрим, как передать выражения в директиву. В реальных случаях вам может потребоваться передать определенную функцию (выражение) в директивы, чтобы предотвратить соединение. Иногда директивам не нужно много знать о идее, лежащей в основе выражений. Например, директива понравится вам, но она не знает, как это сделать. Для этого вы можете следовать такой структуре:


В этой директиве выражение будет передано кнопке директивы через атрибут like . Давайте определим функцию в контроллере и передадим ее в директиву внутри HTML.

Это будет внутри контроллера, и шаблон будет следующий:

likeFunction() поступает из контроллера и передается в директиву. Что делать, если вы хотите передать параметр в likeFunction() ? Например, вам может потребоваться передать значение рейтинга для likeFunction() . Это очень просто: просто добавьте аргумент функции внутри контроллера и добавьте элемент ввода в директиву, чтобы потребовать начальный счет от пользователя. Вы можете сделать это, как показано ниже:

Как вы можете видеть, текстовое поле поступает из директивы. Значение текстового поля привязано к аргументу функции, как например like() . star — для функции контроллера, а starCount — для привязки значения текстового поля.

5. Наследование директивы

Иногда у вас может быть функция, которая существует в нескольких директивах. Они могут быть помещены в родительскую директиву, чтобы они были унаследованы дочерними директивами.

Позвольте мне привести пример из реальной жизни. Вы хотите отправлять статистические данные всякий раз, когда клиенты перемещают курсор мыши в начало конкретной книги. Вы можете реализовать событие щелчка мыши для директивы книги, но что, если она будет использоваться другой директивой? В этом случае вы можете использовать наследование директив, как показано ниже:

Это родительская директива, которая наследуется дочерними директивами. Как вы видите, есть атрибут контроллера директивы, использующий директиву «as». Давайте также определим этот контроллер:

В этом контроллере мы просто устанавливаем экземпляр контроллера переменной bookType с помощью дочерних директив. Всякий раз, когда вы нажимаете на книгу или журнал, тип элемента будет отправлен во внутреннюю службу (я использовал функцию alert только для отображения данных). Как дочерние директивы смогут использовать эту директиву?

Как вы можете видеть, дочерние директивы используют ключевое слово require для использования родительской директивы. И еще один важный момент — это четвертый аргумент функции ссылки в дочерних директивах. Этот аргумент относится к атрибуту контроллера родительской директивы, который означает, что дочерняя директива может использовать функцию контроллера setBookType внутри контроллера. Если текущий элемент является eBook, вы можете использовать первую директиву, и если это журнал, вы можете использовать второй:

Дочерние директивы — это как свойство родительской директивы. Мы исключили использование события щелчка мыши для каждой дочерней директивы, поместив этот раздел в родительскую директиву.

6. Отладка директивы

Когда вы используете директивы внутри шаблона, то, что вы видите на странице, является скомпилированной версией директивы. Иногда вы хотите увидеть фактическое использование директивы для целей отладки. Чтобы увидеть несжатую версию текущего раздела, вы можете использовать ng-non-bindable . Например, допустим, у вас есть виджет, который печатает самые популярные книги, и вот код для этого:

Переменная области видимости книги исходит от контроллера, а вывод этого выглядит следующим образом:

Если вы хотите узнать использование директивы за этим скомпилированным выводом, вы можете использовать эту версию кода:

На этот раз вывод будет выглядеть следующим образом:

Это здорово, но что, если мы хотим увидеть как некомпилированные, так и скомпилированные версии виджета? Настало время написать настраиваемую директиву, которая будет выполнять расширенную операцию отладки.

В этой директиве мы клонируем элемент, который находится в режиме отладки, так что он не изменяется после некоторого набора операций. После клонирования удалите директиву custom-debug , чтобы не действовать как режим отладки, а затем скомпилируйте его с помощью $complile , который уже встроен в директиве. Мы выделили стиль для элемента режима отладки, чтобы подчеркнуть его. Окончательный результат будет следующим:

Вы можете сэкономить время разработки, используя эту директиву отладки, чтобы обнаружить основную причину любой ошибки в вашем проекте.

7. Тестирование директив

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

Я буду использовать Jasmine для модульного тестирования и Karma для тестировщика модулей. Чтобы использовать Karma, просто установите его глобально, запустив npm install -g karma karma-cli (на вашем компьютере должны быть установлены Node.js и npm). После установки откройте командную строку, перейдите в корневую папку проекта и введите karma init . Он задаст вам пару вопросов, как показано ниже, чтобы настроить свои тестовые требования.

Я использую Webstorm для разработки, и если вы также используете Webstorm, просто щелкните правой кнопкой мыши по karma.conf.js и выберите «Запустить karma.conf.js». Это выполнит все тесты, настроенные в конфиге karma. Вы также можете запускать тесты с помощью командной строки karma start в корневой папке проекта. Это все о настройке среды, поэтому давайте перейдем к тестовой части.

Предположим, что мы хотим проверить директиву книги. Когда мы передаем заголовок в директиву, он должен быть скомпилирован в детальное представление книги. Итак, давайте начнем.

В вышеприведенном тесте мы тестируем новую директиву booktest . Эта директива принимает аргумент title и создает div, используя этот заголовок. В тесте перед каждым тестовым разделом мы сначала вызываем наш модуль masteringAngularJsDirectives . Затем мы создаем директиву booktest . На каждом этапе тестирования будет протестирован вывод директивы. Этот тест предназначен только для проверки значения.

8. Тестирование области действия директивы

В этом разделе мы проверим область видимости директивы booktest . Эта директива генерирует подробное представление книги на странице, и когда вы нажимаете этот раздел сведений, переменная области видимости, называемая viewed , будет установлена как true . В нашем тесте мы проверим, установлено ли viewed в true, когда событие click активировано. Директива:

Чтобы установить событие в элемент в AngularJS внутри директивы, вы можете использовать атрибут link . Внутри этого атрибута у вас есть текущий элемент, непосредственно связанный с событием клика. Чтобы проверить эту директиву, вы можете использовать следующее:

В тестовом разделе событие click запускается с помощью element.triggerHandler(«click») . Когда запускается событие клика, переменная viewed должна быть установлена как true . Это значение проверяется с помощью expect(element.isolateScope().viewed).toBe(true) .

9. Заключение

Для разработки модульных и тестируемых веб-проектов AngularJS является лучшим выбором. Директивы являются одним из лучших компонентов AngularJS, и это означает, что чем больше вы знаете о директивах AngularJS, тем более модульные и тестируемые проекты вы можете разработать.

В этом уроке я попытался показать вам лучшие практические рекомендации в отношении директив, и имейте в виду, что вам нужно много практики, чтобы понять логику директив. Надеюсь, эта статья поможет вам хорошо понять директивы AngularJS.

# 14 Общение контроллера и директивы в AngularJS

Сегодня мы поговорим о том, как директива в AngularJS взаимодействует с контроллером.

Создадим новый контроллер в файле index.html:

А теперь описываем контроллер в файле main.js, передав в функцию в качестве переменной $scope:

Далее создаем директиву. Для этого внутри контроллера, в файле index.html, прописываем:

Следующий шаг — описание директивы в main.js:

Внутри директивы мы возвращаем объект с link функцией, которой, в качестве параметров передадим три аргумента — scope, element, attrs. Внутри функции выведем console.log(). Давайте в контроллере также пропишем console.log().

В консоли браузера первой строкой мы видим controller scope, а во второй строке — scope директивы.

Для того, что было понятнее, давайте создадим, в описании контроллера, переменную $scope.posts и присвоим ей пустой массив:

Теперь, если в консоли браузера мы посмотрим на оба эти scope, то мы увидим, что они абсолютно идентичны, так как оба содержат posts: Array[0]. Это произошло потому, что по умолчанию директива наследует scope контроллера, в котором она была инициализированна. Это значит, что в директиве scope равен $scope контроллера. По сути, это тоже самое, если мы в директиве пропишем property — scope: false, который стоит у директивы по умолчанию:

Данный способ позволяет легко коммуницировать директиве с контроллером, но нужно быть очень внимательным при его использовании. Почему? Сейчас увидим.

Создадим в контроллере новую переменную hello

И выведим ее в нашем index.html над директивой:

В браузере отображается наша переменная. Представим ситуацию — мы забыли, что у нас в директиве прописано scope: false, или мы могли его вообще не определить, так как он подразумевается по умолчанию. Затем, в link функции, создадим переменную с аналогичным названием — hello

Обновим браузер и посмотрим что же произошло. Переменная, которую мы создали в контроллере, уже не выводится. Вместо Hello мы видим — Hi. Все дело в том, что директива имеет возможность менять $scope контроллера как угодно. Об этом всегда нужно помнить, поскольку директива может изменить любую переменную, а вы даже не заметите. Поэтому, если вы пишете директивы, которые затем планируете переиспользовать, то scope: false лучше не прописывать.

Удалим переменную hello из контроллера и директивы. Теперь давайте заполним массив в контроллере:

Тперь, в директиве, мы можем использовать эти самые posts. В консоли браузере, при инспектировании scope директивы, мы видим, что значение posts содержит уже Array[2]. Поэтому далее в директиве, мы создаем template, в котором выводим все наши posts

В браузере мы видим оба наши поста из нашего контроллера, которые мы вывели на экран при помощи директивы. Данный способ достаточно удобен, но не является правильным с точки зрения разделения логики. Ведь мы можем легко модифицировать posts, который находится внутри контроллера.

Для того, чтобы код был более читабельным — мы можем создать в контроллере публичную функциию, которая будет возвращать содержимое нашего posts

Не забываем изменить переменную на функцию в дириктиве:

Наш код работает точно также и не возникнет никакой проблемы в том случае, если posts будет изменен. Функция getPosts будет работать без изменений, так как она не привязана к какой-либо переменной.

Помните о том, что scope директивы, при указанном значении false, будет равняться $scope контроллера.

Шпаргалка по AngularJS

Эта статья позволит быстро освоить основы JavaScript-фреймворка AngularJS.

Другие статьи по AngularJS:

С чего начать

    1. Подключаем скрипты фреймворка на страничку (взять можно здесь), как минимум, Вам потребуются: angular.js, angular-route.js, angular-locale_ru-ru.js. В рассматриваемом здесь приложении мы используем анимацию, поэтому добавим еще и angular-animate.js.
    2. Создаем app.js — это будет «точка входа» в приложение angular. Внутри объявляем корневой модуль приложения и его зависимости, конфигурируем роуты; если нужно, определяем функцию, которая выполнится при старте приложения, и оборачиваем все это в вызов анонимной функции, «чтобы наружу не торчало ничего»:

    Рассмотрим код подробнее.
    Конструктор модуля принимает два аргумента — имя модуля и массив имен модулей, от которых он зависит.
    Функция config выполняется в момент старта приложения, здесь, во-первых, задается роутинг, а во-вторых, конфигурируются сервисы, предоставляемые провайдерами… ок, мы еще вернемся к этому.
    При конфигурации маршрутов мы задаем url шаблона, который нужно использовать для рендеринга (также можно прямо на месте строкой передать inline-шаблон, только не в templateUrl , а template , но лучше так не делать вообще никогда). Часто здесь же параметром controller обычно задается контроллер (сюрприз!), который будет использоваться для взаимодействия с шаблоном, но мы этого делать не будем, позже объясню почему.
    Функция run выполняется после загрузки всех модулей, нам нечего делать на этом этапе, поэтому мы ничего не делаем в ней (то есть ее можно было вообще не передавать в .run()). Но, к примеру, здесь можно получить текущего пользователя из сессии и сохранить его $rootScope.
    А что за $rootScope ? Для начала стоить сказать, что такое $scope . Скоуп — это модель, «клей» между логикой и шаблонами. Скоупы компонуются и наследуются, образуя древовидную структуру, в контексте скоупов выполняются выражения в шаблонах, скоуп может следить ( $watch ) за выражениями (а также функциями, коллекциями, переменными) и бросать события. Все, что есть в скоупе — доступно в связанном с ним шаблоне и в его дочерних скоупах. На самом деле, я сейчас просто пересказал вступление к статье по скоупам из официальной документации, поэтому советую все же заглянуть в первоисточник.
    Теперь, когда мы разобрались (разобрались же?), что такое скоуп, можно пояснить, что такое $rootScope — это, как не трудно догадаться, родительский скоуп всех скоупов в приложении. Ключевые моменты:

    • Одна штука на приложение
    • Доступен из любого места приложения, достаточно внедрить $rootScope
    • Ловит все события
    • Соответственно, события, брошенные им, дойдут до любого дочернего скоупа
    • Превращается в помойку при злоупотреблении
  1. На страничке приложения в тэг html или body добавляем директиву ng-app=»dummy» тем самым заявляя, что внутри этого тэга будет работать angular-приложение dummy, точка входа в которое описана в одноименном модуле.
  2. Где-то внутри body добавляем блок с директивой ng-view — здесь будут рендериться наши шаблоны в соотстветствии с текущим роутом.

Это основные приготовления для angular-приложения. Теперь, прежде чем начать штамповать контроллеры и сервисы, замолвим слово про структуру приложения.

Структура приложения

Следуя рекомендациям разработчиков Angular, структура должна выглядеть примерно так:

Корневая директория называется по имени самого приложения, в ней лежат: контроллер верхнего уровня (app-controller.js), базовые стили приложения (app.css), дефолтный шаблон (app.html) и главный модуль приложения (app.js).

  • разделы приложения (foo и bar), каждый со своими контроллером, шаблоном и стилями;
  • компоненты: здесь храним директивы, сервисы и т.д., которые разделяются по функционалу/сущностям, к которым они относятся (например, все, что имеет дело с message, лежит в одной директории), каждая директива лежит отдельно от другой;
  • конфигурация — здесь, соответственно все constant и value сервисы (url-config.js) и модуль (config.js), в котором все это содержится.


Предлагаемая структура — иерархическая, например, если раздел foo у нас сильно усложнится и мы решим разбить его на части, то файлы дочерних разделов уже будут храниться в поддиректориях foofoo/customer«, «foo/supplier«).

Структура модулей соответствует файловой, то есть сервисы MessageManagerFactory и MessageService содержатся в модуле dummy.message , директива MessageList — в модуле dummy.message.messageList , директива MessagePoster — в модуле dummy.message.messagePoster (да, каждая директива хранится в собственном модуле).

Контроллер

Контроллер — это функция-конструктор, которая используется для «оживления» шаблона. Типичный сценарий использования: шаблон привязывают к контроллеру на этапе конфигурации, в контроллер передают $scope , набивают его под завязку всеми данными и логикой, которые используются на странице, а потом пытаются совладать с 600-строчным чудовищем. Так делать не надо.
Во-первых, $scope нужно использовать только тогда, когда без него не обойтись вообще никак, то есть вызов $watch , $emit , $broadcast и т.д. Все функции, объекты и поля лучше держать в экземпляре контроллера:

В данном случае, в конструкторе мы инициализируем поле saidHi , создаем экземпляр MessageManager , в котором инкапсулируем работу с сообщениями, а также создаем пустой массив для хранения сообщений. Функции, которые будем использовать в шаблоне, выносим в прототип.

Убирая код, работающий с сообщениями в MessageManager , мы не только уменьшаем количество кода в контроллере (что само по себе хорошо), но и избавляемся от зависимостей, которые этот код может за собой тащить. (Да, конкретно для данного случая — это overkill, MessageManager всего-то умеет дергать сервис для отправки/получения/удаления сообщений и выполняет простые callback’и, но идея, думаю, ясна).

$scope же здесь используется только для задания обработчика события message.new.local (мы ждем, что один из дочерних контроллеров или директив может создать новое сообщение).

В шаблоне все это используется так:

AppController объявлен как «главный» контроллер приложения, поэтому он будет доступен везде как appCtrl . Это удобно, но так же, как и с $rootScope этим лучше не злоупотреблять. В данном приложении мы используем эту возможность для доступа к списку сообщений в дочерних контроллерах.

Использование в шаблоне членов экземпляра контроллера, а не скоупа, защищает нас от трудноуловимых багов — мы всегда точно знаем, что именно будет использоваться. Кроме того, двухсторонний биндинг примитивов в дочерних скоупах будет работать корректно без дополнительных оберток.

Кстати, если бы мы задали контроллеры и для маршрутов на этапе конфигурации, и непосредственно в шаблонах, то функции контроллеров вызывались бы дважды, что, естественно, нежелательно.

В самом шаблоне, все достаточно просто: показываем «приветствие» из поля greeting , которое меняется по клику на кнопку «Say Hi». Далее у нас подключена директива messageList для вывода списка сообщений. Для запросов к серверу для получения, отправки и удаления сообщений служат три кнопки «Save new», «Get all», «Delete all», а статус выполнения запроса выводится чуть ниже.

Директивы

Директива — это независимый компонент, предназначенный для многократного использования. Стоит заострить на этом внимание, т.к. не нужно создавать директиву на каждую форму приложения — если форма специфична для конкретной страницы, и вы сомневаетесь, что она может понадобиться где-то еще — не надо делать из нее директиву. Если нужно разгрузить шаблон и контроллер — просто вынесите код в частичный шаблон и напишите для него отдельный контроллер.

Директивы можно разделить на два типа: изменяющие поведение элемента (draggable, collapsable и т.д.) и кастомные ui-компоненты (контрол для пагинации, календарь, модальное окно).

Директива должна делать одну и только одну вещь, не нужно собирать мега-комбайны, делающие все на свете.

Рассмотрим код простой директивы, оборачивающей элемент в «гармошку» — collapsable:

Для создания директивы нужно вызвать метод directive() у модуля, передав туда имя директивы и массив с внедряемыми зависимостями и, собственно, с конфигурационной функцией, определяющей поведение директивы. В данном случае зависимостей нет, поэтому в массиве всего один элемент — функция.

Для данной директивы нам потребовалось задать всего четыре параметра:

1) restrict — определяет, в качестве чего можно использовать директиву, возможные варианты: A — атрибут, E — элемент, и, с недавних пор, С — класс.

2) link — основная функция для «поведенческих» директив, здесь мы имеем доступ к $scope , jqueryLite-обертке элемента, к которому директива применена, и его атрибутам (в виде хэша). link выполняется после того, как манипуляция с DOM (для этой директивы) была завершена.

3) transclude — с этим все не так просто. Если установлен в true , изменяет скоуп директивы так, что его содержимое замещается содержимым родительского скоупа. Таким образом, если и в скоупе директивы, и в скоупе контроллера задать одноименные поля, в шаблоне директивы использоваться будет поле из скоупа контроллера. Этот параметр следует использовать только вместе c директивой ng-transclude , для подстановки фрагмента DOM извне в «тело» директивы — вставленный фрагмент шаблона не потеряет доступ к переменным в родительском $scope, если он их использовал, и нам не придется передавать их в качестве параметра (ну и если не выставить trancslude в true , у вас вылетит Error: orphane ng-transclude directive ). В данном случае, список сообщений (message-list) будет «подставлен» внутрь блока div в шаблоне директивы с атрибутом ng-transclude (при этом все текущее содержимое div’a будет удалено).

4) templateUrl — url, по которому будет запрошен шаблон для директивы.

Теперь рассмотрим директиву с изолированным скоупом — messageList :

Здесь в конфиге директивы три новых параметра:

  1. scope — если сюда передать хэш (даже пустой), у директивы будет изолированный скоуп (неизолированный скоуп прототипически наследует родительский). Заполняется этот хэш таким образом, что ключ — это название свойства у скоупа, а значение — имя атрибута, значение которого будет связано с этим свойством. На то, как именно будут «забиндены» значения атрибутов на свойства в скоупе, влияют префиксы перед именем атрибута:
    • @ — значение из атрибута будет передано в свойство скоупа директивы строкой.
    • & — свойство директивы будет функцией, интепретирующей выражение, содержащееся в атрибуте. Именно этот префикс используется здесь. Таким образом, вызов $scope.getMessages() вызовет appCtrl.getMessages() и вернет массив сообщений.
    • = — свойство скоупа директивы будет «забиндено» на объект, имя которого указано в атрибуте, т.е. будет создана двухсторонняя связь.
    • ? — флаг необязательности наличия значения, используется в дополнение к другим.
  2. controller — имя контроллера, который будет прикреплен к шаблону директивы.
  3. replace — если установлен в true, блок директивы будет заменен контентом шаблона директивы.

В контроллере директивы можно также увидеть использование функции $watchCollection — angular будет следить за состоянием массива или хэша, если его состояние изменится, будет вызвана callback функция с двумя параметрами — newValue и oldValue .

В шаблоне мы выводим список сообщений в messages с помощью ng-repeat , при этом выполняется сортировка по полю, имя которого хранится в sortBy , sortBy при этом задается из select’a.

Для каждого сообщения мы выводим дату, при этом форматирование выполняется с помощью фильтра angular’a date .

Сервисы

Видов сервисов в angular — пять штук:

Неизменяемый объект или примитив. Может быть использован на этапе конфигурации.

  • value — изменяемый объект или примитив. Не может быть использован на этапе конфигурации.
  • factory — сервис, возвращающий какой-либо объект (неважно какой). Приведем фрагмент фабрики MessageManagerFactory :

    В фабрике определена функция-конструктор объектов MessageManager , заданы методы прототипа MessageManager , приватные функции вынесены в хэш _private , и объявлена «статическая» приватная функция _filterNew (статическая в том смысле, что не обращается к членам экземпляра MessageManager ). На выходе фабрики — литерал объекта с единственным методом — make .
    service — отличается от фабрики тем, что при первом использовании функция будет использована как конструктор объекта. Приведем код нашего сервиса сообщений:

    В сервисе определяется конструктор объектов Message (возможно, не самое лучшее решение, да); url для вызова api сервера берется из constant сервиса urlConfig ; для экземпляра самого сервиса определены методы для вызова сервера ( post , delete , get ), метод для создания экземпляра Message и метод для конвертации из json, пришедшего с сервера, в объект Message (все сообщения с сервера конвертируются, таким образом, все наши сообщения в angular-приложении — экземпляры Message ).
    provider — сервис, который можно использовать, если требуется некая конфигурация при старте приложения. В таком сервисе должна быть определена функция $get() , результат выполнения которой будет предоставлен клиенту сервиса. В сам провайдер можно добавить какие-либо функции для его конфигурации:

    Создав таким образом провайдер, мы можем использовать его в функции configure на старте приложения и задать значение параметра someConfigurableParam .

    Подробнее о наследовании $scope

    Скоупы в большинстве случаев ( ng-include , ng-switch , ng-controller , ng-transcluded , директивы с параметром scope: true ) наследуются прототипически (не уверен, что есть такое слово), из чего следует:

    • Изменение примитива в дочернем скоупе создает новое поле в нем, не оказывая эффекта на этот примитив в родительском скоупе.
    • Изменение поля в объекте в дочернем скоупе изменяет это поле в соответствующем объекте в родительском скоупе.
    • Изменение ссылки на объект в дочернем скоупе создает новую ссылку в нем, ссылка в родительском скоупе не изменяется.

    Стоит отметить, что ng-repeat создает новый скоуп для каждой итерации, значения полей которого копируются из соответствующего элемента итерируемой коллекции родительского скоупа. Поэтому не стоит использовать массивы примитивов в ng-repeat , разве что только для read-only.

    Скоупы не наследуются прототипически в следующих случаях:

    1. Создание директивы с параметром scope: false (по умолчанию). В данном случае, директива использует родительский скоуп как свой собственный, что естественно нежелательно использовать, т.к. может привести к трудноуловимым багам.
    2. Создание директивы с параметром scope: <> . Как уже говорилось выше, создает изолированный скоуп. Поля такого скоупа никак не связаны с родительскими, однако доступ к его полям (родителя) можно получить через атрибуты-параметры директивы (используя биндинги ‘@’, ‘&’ и ‘=’).

    Доступ к родительскому, соседнему или дочерним скоупам можно получить с помощью следующих свойств: $scope : $parent , $$nextSibling , $$childTail и $$childHead .

    Подробнее обо всей этой кухне можно почитать здесь.

    О применении $scope.$apply()

    Вызов этой функции заставляет angular обновить состояние шаблона в соответствии c актуальным состоянием шаблона, однако, если вам пришлось использовать это — скорее всего, вы сделали что-то неправильно: использовали setTimeout вместо $timeout , setInterval вместо $interval , element.on(‘click’) вместо ng-click и т.д. В редких случаях использование $apply оправдано — необходимо изменить модель извне angular -приложения, но мне пока не приходилось с таким сталкиваться. В таких случаях использовать $apply нужно следующим образом (украдено отсюда):

    И далее вызываем safeApply() везде, где нам требуется вызов $apply() .

    Ссылка на репозиторий демо-приложения на гитхабе: ng-help.

    AngularJS: Как сделать динамическое подключение директивы?

    Доброго времени суток!
    Суть проблемы в следующем:
    Информация подгружается в модальные окна с помощью AJAX. Хочу по клику на элемент из списка передавать в контроллер название директивы. В создающемся модальном окне классу элемента присваиваю значение этой директивы, но окно открывается пустым. Если заранее прописать название директивы в класс, то окно придет заполненным. Искал информацию, везде про $compile написано, но вот как его приладить я не пойму. Кроме того, везде в примерах все написано хардкодом, весь html прямо в директиве, а я хочу чтобы весь html был в html-файлах, а JS был JSом.
    Вызываю функцию открытия модального окна:

    Контроллер, который создает модальное окно. pageName — передаваемое мной значение названия директивы

    Директива, которая в данном случае должна подключиться:

    Код модального окна, в подставляется класс, через который должна подключаться директива, но она подключается только в случае, если я прописываю ее заранее, вручную. Динамически не хочет работать.

    • Вопрос задан более трёх лет назад
    • 1074 просмотра

    Видимо, в моем случае возможен только «плохой вариант» — $compile.
    Как я ни пытался по-другому приладить директиву на родину, ничего не вышло.
    С помощью официальной доки сделал следующее:

    В контроллере, который создает окно jqxwindow, определяем html:

    После этого у меня в модальном окне стали динамически подгружаться нужные директивы в зависимости от значения pageName.
    Думаю, что вышеприведенный код еще можно причесать для большей красоты, пока еще этим не занимался и не очень понимаю, как оно работает.. Но работает 🙂

    #2 — Directive, Controller, Module.

    Наше увлекательное изучение основ Angularjs продолжается.

    На этом видеоуроке мы начнем разбирать директивы ангуляр. Вы научитесь правильно их записывать.
    Познакомитесь с такими директивами как ngApp, используемая для автозагрузки приложения, ngInit,
    из названия которой следует, что она инициализирует приложение, ngBind, которая позволяет не
    использовать характерные для Angular двойные фигурные скобки.

    Ну, и конечно, будет рассмотрена одна из наиболее значимых директив ангуляр, которая имеет
    место в каждом приложении на Angularjs, — это директива ngController. Её функция заключается
    в инициализации объектов контекста.

    На занятии также вы узнаете, что такое module и для чего он нужен. Module позволяет нам создавать
    приложение как бы отдельными блоками, по частям. Все эти базовые вещи помогут вам в дальнейшем
    освоении PhoneCat-приложения.

    Приятного всем просмотра! Учитесь с удовольствием!

    Angular — Директивы и использование модуля

    Изучив различные проекты и прочитав как можно больше документации, я столкнулся с проблемой включения директив в свое приложение. Приложение настроено следующим образом:

    app.js — только верхняя часть

    Все модули работают отлично, за исключением (это приложение, переписанное из примера) для директив, которые не работают вообще:

    directives.js — следующее НЕ работает и не выполняет директиву в представлении:

    Следующий файл в том же файле directives.js работает правильно, и директива выполняет:

    Мой вопрос в том, как правильно включить набор директив и, возможно, почему первый пример (с использованием ngDashboard.services) не работает.

    Оказывается, что файл app.js, который у меня был, был либо кэширован, что и директивная зависимость не была там, либо я забыл ее сохранить (оба возможны с работой на выходных и поздними ночами). Поскольку эта проблема была исправлена ​​после того, как я сделал обновление для app.js, я помечаю это как разрешенное с помощью:

    • Проверьте консоль скриптов, чтобы убедиться, что ваши файлы не кэшированы.
    • Полностью отключите кеширование или используйте режим инкогнито.
    • Всегда убедитесь, что ng-приложение добавлено в ваш документ (это было не так, но могло помочь кому-то другому).
    • Убедитесь, что вы сохранили ваши файлы.
    • Выпейте больше кофе, когда устали, и изучите новый язык программирования/рамки.

    Наконец, что касается Angular, я не понял, что вы можете добавить директивы в модуль ng , и они станут доступными. Я уверен, что это не лучшая практика, но для тестирования и сборки быстрого кода это может пригодиться.

    AngularJS. Директивы и модули

    201 просмотра

    2 ответа

    30 Репутация автора

    У меня есть следующий код JavaScript, и я столкнулся с проблемой:

    Мой файл .js

    В настоящее время я использую контроллер ‘MainCtrl’ в моей директиве. Но возможно ли поместить весь контроллер в директиву и при этом заставить его работать в обычном режиме?

    что я хочу в моем окончательном файле .js

    Ответы (2)

    плюса

    1580 Репутация автора

    Вы можете просто сделать это, поместив функцию внутри директивы:

    плюса

    38872 Репутация автора

    В конце я должен был бы упаковать мою директиву в файл .js так, чтобы мои одноклассники могли использовать это, просто вызывая имя директивы и помещая в файл .js директивы

    Чтобы упаковать директиву и контроллер в один модуль:

    sai.js

    Затем одноклассники используют его, добавляя модуль в качестве зависимости к своим приложениям:

    Сервисы, фильтры, провайдеры, константы и т. Д. Также могут быть добавлены в модуль.

    Для получения дополнительной информации см. Справочник по AngularJS Module API .

    Топ-пост этого месяца:  Yii2 валидация. Валидация форм в Yii2
    Добавить комментарий
  • Тип Применение
    A