AngularJS. Создание дирекив. Урок 2


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

AngularJS. Создание дирекив. Урок 2

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

Создадим свою директиву. Для этого в папке js создадим новый файл answerList.js со следующим содержанием:

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

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

В качестве названия используется «answerList». Согласно соглашениям об именовании любая буква в верхнем регистре расценивается как начало нового слова, которое будет отделено от предыдущего дефисом. То есть для AngularJS «answerList» будет представлять «answer-list» или «answer-List».

В функцию создания директивы передается три параметра:

scope — объект $scope, установленный в контроллере

element — элемент, к которому применяется директива

attrs — коллекция атрибутов в виде пары ключ-значение, где ключом является название атрибута

Например, далее мы будем передавать объект $scope.question в эту директиву:

В данном случае элементом является элемент div , а коллекция атрибутов будет содержать единcтвенный атрибут — директиву answer-list . А question — это объект $scope.question

И в строке var data = scope[attrs[«answerList»]]; мы как раз получим этот объект question, переданный в директиву. Но фактически мы могли пойти и другим путем — сразу получить данный объект без использования коллекции атрибутов:

Далее мы можем уже обращаться к объектам, которые заключены внутри $scope.question: data.answers . Но перед обращением мы проверяем, является ли нужный нам объект массивом: angular.isArray(data.answers)

Дальше в директиве идет создание html-элементов и перебор элементов внутри массива data.answers. Для создания элементов применяется функция angular.element() , а для добавления созданных элементов в другой — метод append()

Применим директиву на главной странице:

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

Создание директив в angular.js

Продолжаю на работе терзать и наслаждаться возможностями angular.js. Сегодня мне потребовалось подключить к своему проекту плагин DatePicker из пакета jQuery UI. Заповеди angular.js диктуют использовать в представлении директивы, а не хаотичной раскиданный JavaScript код. Следовательно, вот так просто воспользоваться возможностями плагина DatePicker не получится. Точней получится, но делать это ни в коем случае нельзя, ибо это идет в разрез с идеологией angular.js. К счастью, пойти правильным путем ничуть не сложней. Достаточно написать собственную директиву и использовать в разных участках приложения. Под катом я разберу процесс написания директивы для angular.js максимально подробно.

За основу возьмем заготовку проекта – «angular-seed». Склонируй ее из GIT и приготовься вносить изменения. Поскольку конечной целью будет подключение компонента DatePricker, нам потребуется добавить библиотеку jQuery UI к проекту. Загружаем все необходимое с официального сайта библиотеки (или ставим через bower), распихиваем в соответствующие директории проекта и подключаем все это добро в «index.html»:

Создаем директиву

Код директивы будем писать в файле «directives.js». Открываем файл и пишем в него код:

Если говорить кратко, то в этой директиве происходит подключение плагина DatePicker. Правда, меня, когда я впервые увидел подобную конструкцию, краткий ответ не устроил. Да, мы видим, что большую часть этого листинга занимает конструктор DatePicker, но почему он записывается именно в функции link, с кучей параметров? Об этом расскажу ниже.

Зачем нужны директивы в angular.js

Как ты уже знаешь, директивы необходимы для расширения функционала и поведения существующих html-элементов. Например, мы хотим, чтобы список у элемента управления «select» выпадал вверх, а не вниз. Мы можем это сделать средствами jQuery прямо в коде, но это будет НЕ angular-way. Правильней оформить этот код в виде универсальной директивы, и в дальнейшем использовать ее там, где это необходимо. Директивы – это шаг в сторону модульности и повторного использования кода.

Если ты сомневаешься в целесообразности создания директивы в определенных случаях, то задай себе пару контрольных вопросов:

  • Требуется ли мне из контроллеров/сервисов взаимодействовать с DOM?
  • Требуется ли мне писать JS-код в представлениях?
  • Потребуется ли мне подключение jQuery кода в разных участках приложения?

    Наличие положительного ответа на один из перечисленных выше вопросов — гарантия плохой архитектуры и отсутствие понимания идеологии angular. Такие вещи нужно сразу присекать.

    Ок, возвращаемся к нашему коду. Чтобы начать использовать директиву ее необходимо зарегистрировать. Регистрация новой директивы выполняется с помощью метода directive(). Он принимает два параметра:

    name (string, object) – название директивы в верблюжьим (camel-case) стиле. Применительно к нашему коду это «myDatepicker».

    directiveFactory (function(), array) — функция-фабрика (factory function). Эта функция должна вернуть объект с настройками для сервиса $compile, отвечающий за компиляцию HTML/DOM в шаблон. Впоследствии он создаст функцию, связывающую skope и наш шаблон.

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

  • require – директивы, которые будут внедряться в контроллер через четвертый параметр связующей (link) функции. В require можно указать как одну директиву, так и массив. В своем примере я подключаю лишь «ngModel». Она потребуется для организации двухстороннего биндинга.
  • link – в свойстве описывается связующая функция (link function). Определение функции выглядит так:

    В качестве параметров применяются:

    scope – область видимости. Будет использоваться директивой для регистрации обработчиков событий (в терминологии angular – watches);

    iElement – экземпляр элемента, в котором будет использоваться директива;

    iAttrs – экземпляр атрибутов элемента;

    ctrl – экземпляр контроллера. Необходимо указывать, если одна из директив элемента, определяет контроллер. В нашем случае в роли контроллера будет выступать ngModelController.

    transcludeFn – признак трансклюзии. Об этом параметре я расскажу в отдельном посте.

    В рассматриваемом примере я опустил пятый вариант и сократил определении link-функции до:

    В теле функции описывается стандартный конструктор элемента DatePicker. Параметры рассматривать не буду, т.к. отношения к angular они не имеют. Затрону лишь определение обработчика onSelect (). Он должен срабатывать во время выбора в календаре какой-нибудь даты и передавать результат пользовательского выбора в scope.

    В теле метода вызывается метод $setViewValue, обновляющий. В качестве параметра метод принимает значение, полученное из представления. В моем случае – это дата, выбранная в DatePicker. После изменения значения нам необходимо оповестить об этом $scope с помощью метода $apply().

    Тестируем директиву

    Директива полностью готова к применению. Подключение к произвольному элементу ввода выполняется следующим образом:

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

    На этой самой ноте мой рассказ заканчивается. Если у тебя есть вопросы – задавай их мне в комментариях. Постараюсь помочь.

    # 7 Пишем простую директиву в AngularJS

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

    Давайте рассмотрим как создаются директивы. Создадим div с атрибутом foo

    Как вы понимаете, такого атрибута в природе нет. Теперь в нашем main.js напишем

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

    Что это такое? Scope — это область видимости данной директивы. Element — это DOM елемент нашей директивы, обернутый в JQlite и attrs — атрибуты этой директивы.

    Давайте посмотрим. Для начала выведем console.log.

    Если мы посмотрим в браузер, то увидим надпись this is my directive. Теперь давайте выведем внутри директивы текст foo.

    Теперь мы видим наш DOM елемент на странице, но это уже не просто div, а директива. Вот этот атрибут foo, который мы задали, определяется этой директивой, и она срабатывает. То, что она срабатывает, мы видим, потому что у нас выводится console.log.

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

    Что такое link? Link в директиве — это функция, которая срабатывает уже после того, как DOM елемент отрисовался на странице. Давайте теперь посмотрим, что такое scope, element и atts.

    Если мы посмотрим в браузер, то увидим, что scope — это обьект, который является областью видимости нашей директивы. Element — это JQlite елемент, внутри него мы видим наш DOM елемент и attrs — это все атрибуты, которые есть на нашей директиве. Например, наш атрибут foo, который пустой, так как мы его не задали.

    Что мы можем сделать с этой директивой? Мы можем на нее применить какие-то JQuery изменения, например

    Если мы посмотрим в браузер, то увидим текст This is my magic directive внутри директивы. Как мы видим, мы можем легко изменять елемент на что угодно после отрисовки.

    Давайте попробуем повесить ивент click на нашу директиву, чтобы при нажатии на нее надпись менялась с foo на bar, и обратно.

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

    Как мы видим, обычный клик отлично срабатывает.

    Теперь давайте проверим, если текст елемента foo, то мы меняем его на bar.

    Повторим еще раз. Мы повесили на елемент click. И проверяем условие при клике. Если текст елемента равняется foo — мы меняем его на текст bar, в другом случае в текст елемента записываем foo.

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

    Мы можем сколько угодно раз нажимать на каждый елемент и он будет менять текст.

    Освоение директив 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. Простые директивы

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

    Топ-пост этого месяца:  Paypal — что это такое, регистрация, пополнение счета и как им пользоваться, а так же как выводить

    В этом виджете есть изображение книги, название, описание, комментарии и рейтинг. Сбор этой информации и включение определенного элемента 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.

    Создание пользовательских директив в 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 с

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


    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

    Блог Makeomatic: разработка сайтов и мобильных приложений

    Angular.JS: основы создания директив

    концепции и практическое применение

    Подготовка

    Модульная структура

    Как я уже писал ранее, AngularJS является достаточно структурированной библиотекой. Практически каждый элемент функциональности выделен в свой модуль: $http, $resource, $route, $location и так далее. Фактически сама библиотека сконцентрирована в модуле Core. Подключать его не нужно (как и многие другие модули, вроде $http), поскольку он входит в основу библиотеки.

    Начиная с версии 1.1.6 модуль $route нужно подключать отдельно, поскольку было принято решение исключить его из ядра и впоследствии объединить с модулем ui.state от команды AngularUI.

    Расширение функциональности

    Следует заметить, что вызов angular.module может работать по-разному в зависимости от переданных ему параметров. Если переданное первым параметром имя модуля соответствует уже существующему модулю, то вызов вернёт ссылку на этот модуль, если же такого модуля нет, то он предварительно будет создан.

    Это позволяет держать код в разных файлах и не заботиться о последовательности их подключения/склейки. Достаточно лишь в начале каждого файла написать

    Разумеется, можно подключать и зависимости, их наличие не влияет на работу функции angular.module .

    Настройка модуля

    Каждый модуль ведёт себя как полноценный элемент приложения и сам может являться приложением (об этом говорилось ранее). Разумеется, что модули можно настраивать, меняя их поведение в зависимости от ситуации. Для этого предназначено две функции:

    Провайдер

    Провайдеры являются фабриками классов. Они создают готовые объекты, которые можно внедрять с помощью DI. Провайдеры являются основным способом расширения функциональности AngularJS. По своей сути, провайдер представляет собой объект, в котором находится единственная обязательная функция с строго регламентированным именем: $get .

    Помимо того, провайдер может включать любые методы, с помощью которых можно настроить создание объектов. Объекты, создаваемые провайдером, обычно называются сервисы.

    Функция $get вызывается инъектором в процессе внедрения зависимостей. Поэтому если написать её тем или иным способом, то можно получить разные результаты: например, всякий раз будет создаваться новый объект, а может и отдаваться ссылка на один и тот же общий. Второй вариант широко применяется для обмена данными между разными частями приложения/модуля.

    Для доступа к самому провайдеру следует добавить к имени сервиса слово Provider . Например, $httpProvider . Следует заметить, что далеко не у всех сервисов есть свой отдельный провайдер, к которому можно получить доступ, как в примере выше.

    Константа

    Константа — это сервис, представляющий собой некую константу. Пример такого сервиса можно увидеть выше. Однако в AngularJS существуют функции для более удобного создания объектов, не имеющих отдельного провайдера, который не нужно настраивать. Для создания сервиса, отдающего некую константу, можно воспользоваться функцией module.value , выглядит это так:

    Эта запись эквивалентна следующей:

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

    Фабрика

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

    Обратите внимание, что я внедрил TheAsnwer в фабрику. Так же можно подключать любые зависимости. Сервисы могут и должны зависеть друг от друга.

    Таким образом, я могу менять в некоторой степени поведение фабрики TheObject , поскольку она зависит от TheAnswer . Но лишь в некоторой степени.

    Сервис

    Сервис это фабрика, которая всякий раз возвращает новый объект. Иными словами, запись

    Можно сократить до

    Но что если в этом случае мы хотим менять передаваемый в процессе создания сервиса параметр? В этом случае нам и нужен полноценный провайдер.

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

    Директивы

    Хорошо, но что если нам нужно не только сделать какой-то сервис или модуль. Что если мы хотим реализовать что-то подобное директиве ngRepeat? Разумеется, AngularJS позволяет делать и это.

    Рассмотрим, что AngularJS делает, когда встречает:

    $parse

    Эта функция превращает любое допустимое выражение AngularJS в функцию. Эту функцию затем можно вызвать, передав в неё 1 или 2 параметра:

    Вторым параметром можно передать локальные переменные, с помощью которых можно временно переопределить переменные внутри контекста — первого параметра.

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

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

    $compile

    $compile делает то же самое, что и $parse, но для HTML. Например

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

    Эта функция тоже вряд ли вам понадобится, но опять же знать о её существовании полезно.

    Первая директива

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

    В результате работы этой директивы вместо

    . Параметр replace позволяет определить, будет ли директива целиком замещать DOM, которому применена, или же встраиваться внутрь него. Параметр template можно заменить на templateUrl и подключать шаблон из файла.

    Наиболее важными параметрами здесь являются scope и link . Последний — это функция, осуществляющая привязку scope к шаблону (см. выше про $compile ). Ну а scope позволяет изолировать область видимости внутри директивы. Эти два параметра следует указывать практически всегда.

    Есть также параметр compile , который позволяет задать обработчик шаблона перед связыванием его с link , но он используется довольно редко.

    Процесс компиляции в AngularJS

    1. Сначала шаблон парсится стандартными средствами браузера. Важно понять, что шаблон должен быть допустимым HTML, иначе ничего не заработает.
    2. Вызывается $compile , который обрабатывает выражения и составляет список обнаруженных директив. Директивы для каждого тега сортируются в порядке важности (его можно указывать при разработке директивы), затем вызываются функции compile у каждой из директив. В этих функциях директива имеет возможность изменить DOM по своему усмотрению. Результатом этого этапа будет одна общая функция линковки, включающая в себя также и все функции link директив.
    3. Вызывается функция, полученная на этапе 2, которая в свою очередь вызывает функции link всех директив, которые могут привязывать обработчики событий и т.д.
    4. Получаем DOM с включенным двойным связыванием, который может динамически меняться.

    Директива практически всегда имеет функцию link и практически всегда не имеет функции compile .

    Полный код создания директивы

    Хотя для простоты вы можете вообще возвращать в angular.directive функцию link :

    Это используется довольно редко. Чаще всего используется вариант из раздела «Первая директива». Однако есть и максимально полный вариант.

    Ограничение применимости

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

    • E: только в качестве собственного элемента DOM:
    • A: в качестве атрибута:

    Эти значения можно комбинировать, например так: restrict: «AC» .

    Изоляция области видимости

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

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

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

    Следует заметить, что если написать

    И определить someName где-то ещё, то директива заработает как и ожидается, но только в одну сторону. Можно поступить несколько иначе:

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

    Продвинутый вариант области видимости

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

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

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

    Вводимые в поле ввода имена будут уникальными для каждой директивы и не помешают друг другу, несмотря на несколько смущающую запись. sayHello(name) — параметр здесь это имя свойства объекта, передаваемого из директивы.

    Всё вышеописанное легко достигается вообще без использования функции link . Однако если вы хотите самостоятельно обрабатывать некие события браузера, она вам понадобится.

    Что на самом деле делают @, =, &?

    @ создаёт одностороннее связывание данных из родительской области видимости.

    = позволяет изолированному в области видимости идентификатору участвовать в связывании (обратите внимание, как сильно это отличается от @)

    & создаёт делегат. Если вы работали с C#, то знакомы с понятием делегата. Если же нет, то я рекомендую обратиться к другим источникам, хотя в общем-то для работы с AngularJS это и не обязательно.

    Подмена

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

    Я намеренно опустил логику создания диалога и сильно упростил итоговый HTML в template . Для настоящей директивы понадобится добавить правильную разметку с кнопкой закрытия, кнопками действия (которые могут настраиваться через дополнительные атрибуты), повешать обработчики событий в функции link и т.д. Однако этот пример позволяет быстро понять, как пользоваться функцией подмены разметки.

    Важно: содержимое тега с директивой ngTransclude будет сохранено. Новая разметка будет добавлена к нему.

    Взаимодействие директив

    Директивы могут взаимодействовать друг с другом с помощью контроллеров. Одна директива может зависеть от другой и вызывать методы и свойства её контроллера.

    ANGULARJS ESSENTIAL УРОК 2 ИСПОЛЬЗОВАНИЕ ПРИВЯЗОК И СТАНДАРТНЫХ ДИРЕКТИВ

    Слушать

    Длительность: 8 мин и 4 сек

    Битрейт: 192 Kbps

    Angularjs Essential Урок 3 Работа C Dom И Валидация Форм

    Ng Include Directive In Angularjs

    Angularjs Essential Урок 1 Введение В Angularjs

    Angularjs Tutorial 2 Installation And Set Up Getting Started With Angularjs

    Angular Tutorial For Beginners Introduction To Angular Directives Write A Custom Directive

    Обзор Курса Разработка Под Android Создание Книги Контактов

    Angularjs For Everyone Tutorial 1 Two Way Data Binding

    Основы Coffeescript 1 Установка Настройка Запуск

    Angularjs Ng Class

    Angular 2 Tutorial For Beginners Learn Angular 2 From Scratch Mosh

    Programming with Mosh

    Angularjs Tutorial What Is Angularjs

    Angular 2 Контроллеры

    Уроки Angular 7 Компоненты

    Angularjs For Everyone Tutorial 11 Including Templates And Inline Svg With Nginclude

    Angularjs Directives Tutorial Part 1 Demystifying Angular Directives

    Создание Директивы В Angular Js

    Angular 3 Обмен Данными Между Контроллерами

    Angular 4 Tutorial 8 Ngif And Ng Template

    Javascript Джедай 1 Введение

    Сейчас скачивают

    Banda Liceo De Costa Rica 15 Septiembre 2012

    Angularjs Essential Урок 2 Использование Привязок И Стандартных Директив

    Following The Transfer Burning By Boet Burnings Step 4

    Asad Sulton Jonim Dadam

    В Махачкале Задержан Мужчина С Автоматом Калашникова

    Murod Manzur Musofir Мурод Манзур Мусофир

    Пётр Лещенко Всё Что Было

    Who Do Buddhists Pray To

    Дима Билан И Polina Пьяная Любовь Новогодняя Ночь На Первом

    Jai Athmavignan Armur Programme

    Update New Headway Beginner Student S Book 4Th Unit 12 Please And Thank You

    Жизнь На Волоске Выпуск 418 22 03 2020 Самые Шокирующие Гипотезы

    Вакханки Теодорос Терзопулос Электротеатр Станиславский

    Bahh Tee 10 Лет Спустя

    Liman Yajroo Fakat S04 Episode 25 19 03 2020 Partie 01

    Урок 2 Angularjs Директивы И Модули

    Длительность: 38 мин и 4 сек

    Битрейт: 192 Kbps

    Похожие песни

    Богбон Кизи Шерали Жураев

    Моцарт Концерт 3 I Часть

    Otash Hijron Xumorim Klip

    Клип Minecraft Звездные Войны Musicvideo 77

    Классный Танец Танцы Флешмоб Танцы 2020 Танец На Последний Звонок

    Shaytanat Music Version

    Хаёл Накун Аз Ту Гузаштам Хануз Хастаам Бехтарин Суруд

    Eng Sara Qo Shiqlar 2020

    Ери Хотин Вашпе

    Otabek Muhammadzohid To Ylar Muborak Jonli Ijro

    Sahale Dakha Brakha Yagydku Remix

    Бахроми Огомамад Дар Бог Мехироми Он Мохи Нав Расида

    Народный Ансамбль Сорока Песня Эх Разгуляй

    Ijtimoiy Tarmoq Uzbek Tilida

    Детскому Саду Буратино 30 Лет

    Bahriddin Zuhriddinov Arazchim

    Спаривание Быка И Коровы

    Эрони Хайфе Делам

    Hazbin Hotel Отель Хазбин Your Fault Clip Русская Озвучка

    AngularJS Essential. Урок 2. Использование привязок и стандартных директив

    Расскажите об этом видео своим друзьям в социальных сетях!

    Автор: ITVDN Качество: HD Просмотров: 25,522 Добавлено: 15 May 2015 Продолжительность: 8m 4s

    Вам так же понравится

    AngularJS Essential. Урок 3. Работа C DOM и валидация форм

    2 Использование привязок и стандартных директив AngularJS

    Ng Include Directive In AngularJS

    AngularJS Tutorial 2 Installation And Set Up Getting Started With AngularJS

    AngularJS For Everyone Tutorial 1 Two Way Data Binding

    AngularJS Ng Class

    �� Angular Tutorial For Beginners Introduction To Angular Directives Write A Custom Directive

    Директивы в Angularjs для начинающих. Часть 2

    На мой взгляд, директивы являются основной изюминкой декларативного стиля Angularjs. Однако, если открыть комментарии пользователей в разделе официальной документации Angularjs, посвященной директивам, то вы увидите, что самый популярный из них: «Пожалуйста, перепишите документацию, сделайте ее более доступной и структурированной. Начинающему разработчику на Angularjs сложно в ней разобраться» («Please rewrite a clearer well structured documentation of directives., this is not friendly to first time angular developers»). С этим трудно не согласится, документация пока еще сыровата и в некоторых моментах приходится прилагать большие усилия, чтобы разобраться в логике и сути функционала. Поэтому я предлагаю вам свой вольный пересказ данной главы в надежде, что кому-то это позволит сэкономить время, а так же рассчитываю на вашу поддержку и участие в комментариях. Итак, поехали!
    Часть 1

    • Как писать директивы?
    • Простой вариант создания директивы
    • Развернутый вариант
    • Link и Compile
    Template и TemplateUrl

    Продолжая разговор о директивах, надо отметить, что директивы по сути являются модулями, если абстрагироваться от терминологии Angularjs. То есть, в идеале, они должны быть самостоятельным элементом интерфейса со своими функционалом и разметкой. Разметка при этом может задаваться напрямую в параметре Template или храниться в отдельном файле, URL которого указывается в TemplateUrl:

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

    Scope

    Параметр Scope определяет область видимости внутри директивы. Возможно несколько вариантов:

    Не указывать scope вовсе. Тогда директива, грубо говоря, работает напрямую в области видимости контроллера. То есть все переменные контроллера равны переменным директивы.

    Другой вариант. Scope = true. В этом случае, scope будет наследоваться. То есть поля, заданные в родительском scope будут отображаться и в scope директивы, но при этом все изменения будут локальны:

    И наконец, самый интересный вариант. Задать изолированный scope. То есть scope, который по умолчанию абсолютно независим от контекста вызова директивы. Для этого нужно просто указать в качестве scope пустой объект <>:

    Дальше есть несколько вариантов работы с таким изолированным scope. Но все они сводятся к одному принципу. В объекте, который мы объявили для scope, в качестве имени свойства слева указывается некая переменная директивы, а справа название атрибута DOM c одним из трех символов в начале: @/=/&. То есть вот так:

    Либо еще одни вариант. Не указывать имя атрибута, тогда оно будет равно имени переменной:

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

    Префикс «=» означает, что в атрибуте передается уже не строчка, а имя некоторой переменной в текущем Scope. И локальная переменная будет напрямую с ней связана. То есть изменения переменной как внутри директивы, так и вне отразятся и там, и там:

    И наконец, последний вариант «&» предполагает, что атрибут содержит некое выражение. К примеру, «c= a+b» или проще «a+b». И теперь ваша локальная переменная становится функцией, в которую можно передавать параметры. Параметры передаются в объекте, ключами которого выступают имена переменных в функции. В конкретном случае, localVar() вернет три.

    При этом интересно, что по умолчанию, если не передавать в локальную функцию никаких параметров, переменным будут присвоены значения соответствующих переменных в родительском scope. А если указать переменную -результат, то и она также будет доступна из вне:

    Топ-пост этого месяца:  Для перевода на русский Google Translate использует искусственный интеллект
    Добавить комментарий
    Тип Применение
    A