Pipes
Содержание:
- Как устроен Angular: компоненты
- Создание эффектов
- Angular 2: новый путь
- Какую версию Angular мне лучше использовать?
- Установка библиотеки
- Пример использования NGRX
- Подводные камни Angular Universal
- ngClass и ngStyle
- Изменения делаются чистыми функциями
- Пример NGRX
- Написание бесполезных селекторов директив
- AngularJS Applications
- Маршрутизация. Используем Route Guard
- Популярные встроенные Angular-директивы [ править | править код ]
Как устроен Angular: компоненты
Angular-приложения состоят из независимых элементов. Эти элементы называются компонентами, и у каждого компонента своё поведение.
Например, лента новостей — один компонент. Отвечает за отображение списка новостей на странице. Кнопка «Прочитать» — другой компонент. Отвечает за переход со страницы списка новостей к выбранной новости.
Обычно компонент программируют так, чтобы он отображал элемент на экране и выполнял какое-то действие. Компонент может реагировать на клик, сворачиваться, разворачиваться, скрываться, перебрасывать на другую страницу и так далее.
Компоненты подчиняются жизненным циклам — меняются и работают по нескольким запрограммированным сценариям. Возьмём ситуацию, когда мы переходим со страницы списка новостей к одной новости. В этом случае компонент «Лента новостей» уничтожается и при необходимости создаётся повторно. Жизненные циклы разгружают память и ускоряют приложение.
Страница с шапкой, лентой новостей и тремя кнопками. Каждый элемент — независимый компонент, который выполняет какое-то действие внутри приложения
Создание эффектов
Вы, наверное, уже заметили, что в редукторах мы не обрабатываем все действия, которые мы создали. Это потому, что мы собираемся обработать пропущенные действия в эффектах, потому что эти действия имеют побочные эффекты.
Давайте начнем с пользовательских эффектов :
Файл с описанием эффектов пользователя
В этом файле у нас много чего происходит. Давайте попробуем объяснить это:
- Мы объявляем наши пользовательские эффекты с помощью декоратора внедряемых зависимостей .
- Мы объявляем наши эффекты, используя декоратор эффектов, предоставленный библиотекой .
- Используя действия, предоставляемые , мы собираемся собрать конвейер наших операторов для этого эффекта.
- Следующим шагом является определение типа действия в эффекте с помощью оператора .
- Следующие части представляют собой операторы , которые мы используем для получения того, что нам нужно (Документация ngrx Справочник RxJS).
- Наконец, в последнем операторе собирается отправить другое действие
- В конструкторе мы внедряем сервисы, которые собираемся использовать, действия для и, в данном случае, хранилище (учтите, что это демонстрационная версия, и мы получаем выбранного пользователя из списка пользователей в нашем локальном хранилище)
Это в значительной степени та же самая структура, которую вы увидите в любом описании эффекта. В этом случае мы отправляем только успешное действие, но мы можем отправлять ошибки или любое другое состояние, которое мы хотим обработать в наших редукторах приложений.
Давайте посмотрим на эффекты конфигурации :
Файл с описанием эффекта конфигурации
И снова, вы, вероятно, чувствуете себя комфортно читая этот код.
Теперь пришло время поговорить о селекторах …
Angular 2: новый путь
Вторая версия ангуляра была заявлена как новый фреймворк, написанный с нуля, в котором учли все ошибки первой части. По мере использования 2-й версии у меня сложилось именно такое впечатление. Лишние сущности и концепции исчезли. То, что осталось, стало только лучше и удобнее, а нововведения хорошо вписываются и выглядят логичными.
Первый ангуляр был, по-сути, просто набором полезных приёмов, техник и паттернов, склееных с помощью DI вместе. Но отдельные его части были как-то сами по себе, были слегка разрозненны. Не было единой концепции.
- Контроллер можно было вставить в DOM кучей разных способов: через атрибут, через роутер (которых уже 3 версии: простой оригинальный, навороченный сторонний, и бэкпорт из 2-й части), через директиву.
- Параллельно DOM-дереву, было дерево с иерархией объектов-скоупов, в которых хранились данные, доступные через контроллеры. Сами скоупы могли наследоваться, почти как прототипы, а могли быть изолированными. Так же были крайне сложные для понимания transclude-скоупы.
- Была своя событийная система, связанная с иерархией скоупов, по которой можно было передавать данные в разные стороны
В итоге, структура приложения могла быть совершенно разной. Но вместо свободы обычно это означало смешивание концепций.
Компонентный подход
Что такое компонент в Angular 2? Это просто класс с определёнными метаданными и связанный с ним слой представления (шаблон). Чтобы сделать из класса компонент, нужно добавить в него эти самые определённые метаданные. Самый простой способ — обернуть его в декоратор , который и связывает представление с его ViewModel (т.е. самим классом). А с точки зрения иерархии типов, компонент — частный случай директивы (которая определяется с помощью декоратора ), у которой есть шаблон:
В декоратор нужно передать объект, который должен содержать минимум 2 обязательных поля: и .
Поле содержит строку, которая будет использоваться в качестве css-селектора для поиска компонента в DOM. Можно передать любой валидный селектор, но чаще всего используют селектор-тэг, не входящий в стандартный набор HTML-тэгов. Таким образом, создаются кастомные тэги.
Поле содержит строку-шаблон, которым заменится содержимое DOM-элемента, найденного по селектору. Вместо строки с шаблоном можно передать строку с путём до файла-шаблона (только поле будет называться ). Подробнее про синтаксис шаблонов можно почитать страницу доков или её русский перевод.
Иерархия компонентов
Что было плохого в первом ангуляре? Там была иерархия скоупов, но сервисный слой был общий для всех. Сервисы настраивались раз и навсегда до запуска приложения, да ещё и были синглтонами.
Ещё были проблемы с роутерами. Оригинальный был довольно скуден, не позволял создавать нормальной иерархии. UI-router был более богат на фичи, позволял использовать несколько view, умел строить иерархию состояний.
Но основная проблема обоих роутеров заключалась в том, что вся эта иерархия путей была абсолютно никак не связана с иерархией скоупов и была крайне не гибкой.
Как же поступили во второй версии? В основе второго ангуляра, как я уже говорил, лежат компоненты. Всё приложение состоит только из компонентов, которые образуют древовидную иерархическую структуру. Корневой компонент загружается с помощью функции bootstrap на HTML-страницу (если используется браузер как целевая платформа). Все остальные компоненты помещаются внутрь корневого и образуют дерево компонентов.
Как же сделать так, чтобы каждый компонент мог бы быть максимально независимым, переиспользуемым и самодостаточным, при этом, избежать дублирования кода?
Чтобы обеспечить компоненту независимость, у него есть метаданные, позволяющие полностью описать всё, что нужно для работы этому компоненту: настройку роутинга, список используемых директив, пайпов и сервисов. Чтобы не быть связанным через сервисный слой, каждый компонент теперь имеет свой роутер и свой инжектор. И они, в свою очередь, так же образуют иерархию, которая всегда связана с иерархией компонентов.
Это и отличает DI в Angular2 от других DI-фреймворков: в ангуляре у приложения нет одного инжектора, у каждого компонента может быть свой инжектор
Какую версию Angular мне лучше использовать?
На данный момент существует две популярные версии Angular. Версия 1 доступна на https://angularjs.org/ и является обновлённой версией того Angular, что был представлен Miško и его командой в 2011 году. Другая популярная версия теперь называется просто Angular и доступна на https://angular.io/. Современный Angular – это полностью переделанная версия для новых браузеров, рабочих процессов и платформ разработки.
Почти во всех случаях вам следует придерживаться последней версии Angular. В ближайшем будущем команда Angular будет стремиться поддерживать Angular 1, но нет никаких оснований полагать, что они будут поддерживать и более старые версии. Более того, Angular 1 не допускает использования библиотеки вне браузера, поэтому вы не можете воспользоваться такими библиотеками, как NativeScript для создания мобильных приложений.
Установка библиотеки
Мы собираемся использовать для создания проекта, а затем добавить библиотеки .
Давайте создадим проект:
ng new angular-ngrx —style=scss
Давайте добавим библиотеки , которые мы будем использовать:
npm install @ngrx/core @ngrx/store @ngrx/effects @ngrx/store-devtools @ngrx/router-store --save
Мы устанавливаем почти все библиотеки экосистемы . Названия большинства из них совершенно ясно представляют их назначение. Например, ядро , хранилище , эффекты . Но есть пара, которая может удивить вас своим предназначением.
- — мощная утилита для отладки.
- — сохраняет состояние маршрутизатора Angular в хранилище.
Пример использования NGRX
Итак, мы закончили с теорией, представив жизненный цикл и его участников, а теперь пришло время посмотреть на это в действии. Из этого легко сделать ещё одну статью. Но, на мой взгляд, нет смысла объяснять всё то, что мы объяснили без примеров реализации. Так мы можем посмотреть всё в действии, скачать и поиграться с кодом.
В нашем примере будет список пользователей, страница сведений о пользователе, и некоторая начальная информация о конфигурации, которую вы должны получить при запуске приложения. Мы собираемся реализовать некоторые важные этапы жизненного цикла .
Вот что это будет:
- Установить библиотеки
- Создать структуру папок для хранилища
- Создать состояние и начальные значения
- Создать действия
- Создать редукторы
- Создать эффекты
- Создать селекторы
- Собрать и настроить всё вместе
- Использовать хранилище в некоторых компонентах
Итак, приступим …
Подводные камни Angular Universal
Не трогайте DOM
Когда мы начали тестировать компоненты нашего магазина с помощью , нам пришлось потратить некоторое время, чтобы понять, почему наш сервер падает при запуске без вывода серверной страницы. Например, у нас есть компонент Session Flow component, который отслеживает активность пользователя во время сессии (перемещения пользователя, клики, рефферер, информация об устройстве пользователя и т.д.). После поиска информации в issues на мы поняли, что в нет обертки над DOM.
.
Если вы склонируете этот Angular Universal стартер и откроете browser.module.ts вы увидите, что в массиве разработчики Universal предоставляют два:
Итак, если вы хотите, чтобы ренедеринг на сервере работал, вы должны заинжектить в свои компоненты эти переменные и обернуть в проверку среды выполнения фрагменты кода, где непосредственно происходит взаимодействие с . Например, вот так:
автоматически добавляет , если это сервер, и , если браузер. Может быть, позже разработчики пересмотрят эту реализацию, и нам не придется беспокоиться об этом.
Если вы хотите активно взаимодействовать с элементами DOM, используйте сервисы API, такие как, или .
Правильный роутинг
Поскольку сервер отражает наше приложение, у нас была проблема с роутингом.
Поэтому не забудьте добавить тот же роутинг на сервере что и на клиенте. Например, у нас есть такие роуты на клиенте:
Тогда нужно создать файл с массивом роутов сервера. Корневой маршрут можно не добавлять:
Наконец, добавьте роуты на сервер:
Пререндеринг стартовой страницы
Одной из наиболее важных особенностей является пререндеринг. Из исследования Kissmetrics следует, что 47% потребителей ожидают, что веб-страница загрузится за 2 секунды или даже менее
Для нас было очень важно отобразить страницу как можно быстрее. Таким образом, пререндеринг в как раз про нашу задачу
Давайте подробнее рассмотрим, что это такое и как его использовать.
Когда пользователь открывает URL нашего магазина, немедленно возвращает предварительно подготовленную HTML страничку с контентом, а уже затем затем начинает загружать все приложение в фоновом режиме. Как только приложение полностью загрузится, подменяет изначальную страницу нашим приложением. Вы спросите, что будет, если пользователь начнет взаимодействовать со страницей до загрузки приложения? Не беспокойтесь, библиотека Preboot.js запишет все события, которые выполнит пользователь и после загрузки приложения выполнит их уже в приложении.
Чтобы включить пререндеринг, просто добавьте в конфигурацию сервера :
Добавление мета-тегов
В случае SEO-ориентированного сайта добавление мета-тегов очень важно. Например, у нас есть , который представляет страницу определенного продукта
Он должен асинхронно получать данные о продуктах из базы данных и на основе этих данных добавлять мета-теги и другую специальную информацию для поискового робота.
Команда создала сервис angular2-meta, чтобы легко манипулировать мета-тегами. Вставьте мета-сервис в ваш компонент и несколько строк кода добавлят мета-теги в вашу страницу:
В следующей версии Angular этот сервис будет перемещен в@angular/platform-server
Кэширование данных
запускает ваш XHR запрос дважды: один на сервере, а другой при загрузке приложения магазина.
Но зачем нам нужно запрашивать данные на сервере дважды? PatricJs создал пример, как сделать Http-запрос на сервере один раз и закэшировать полученные данные для клиента. Посмотреть исходный код примера можно . Чтобы использовать его заинжекте и вызовите метод для выполнения http-вызовов с кешированием:
ngClass и ngStyle
ngClass
Директива ngClass позволяет определить набор классов, которые будут применяться к элементу. В качестве значения она принимает
набор классов в следующем виде:
={ "класс1": true/false, "класс2": true/false, ................... }
Например, определим следующий компонент:
import { Component} from '@angular/core'; @Component({ selector: 'my-app', template: `<div ="{verdanaFont:true}"> <h1>Hello Angular</h1> <p ="{segoePrintFont:true}"> Angular представляет модульную архитектуру приложения </p> </div>`, styles: }) export class AppComponent { }
В секции styles у компонента определены два класса, которые устанавливают различные стилевые свойства шрифта: verdanaFont и segoePrintFont.
В шаблоне для привязки класса к элементу применяется директива . Эта директива принимает js-объект, в котором
ключи — это названия классов. Этим названиям присваиваются булевые значения true (если класс применяется) и false (если класс не применяется). То есть в данном
случае класс verdanaFont будет применяться ко всему блоку div.
Однако в блоке div есть параграф, и мы, допустим, хотим, чтобы к этому параграфу применялся другой класс. А по умолчанию вложенный параграф унаследует стили от
родительского блока div и также применяет класс segoePrintFont, в котором можно переопределить унаследованные стили.
Вместо жестко закодированных значений true/false мы можем использовать привязку к выражениям:
import { Component} from '@angular/core'; @Component({ selector: 'my-app', template: `<div ="{verdanaFont:isVerdana}"> <h1>Hello Angular</h1> <p ="{segoePrintFont:isSegoe}"> Angular представляет модульную архитектуру приложения </p> </div>`, styles: }) export class AppComponent { isVerdana = true; isSegoe = true; }
В качестве альтернативы мы можем использовать следующие выражения привязки:
<div ="true"> <h1>Hello Angular</h1> <p ="false" ="true"> Angular представляет модульную архитектуру приложения </p> </div>
Выражение указывает, что класс verdanaFont будет применяться для данного элемента.
Однако с помощью ngClass мы можем задать целый набор классов, которые применяются к элементу:
import { Component} from '@angular/core'; @Component({ selector: 'my-app', template: `<div ="currentClasses"> <h1>Hello Angular</h1> <p> Angular представляет модульную архитектуру приложения </p> </div>`, styles: }) export class AppComponent { isVerdana = true; isNavy = true; currentClasses={ verdanaFont: this.isVerdana, navyColor: this.isNavy } }
В данном случае для элемента устанавливаются два класса verdanaFont и navyColor.
ngStyle
Директива ngStyle позволяет задать набор стилей, которые применяются к элементу. В качестве значения директива принимает js-объект,
в котором ключи — названия свойств CSS:
import { Component} from '@angular/core'; @Component({ selector: 'my-app', template: `<div ="{'font-size':'13px', 'font-family':'Verdana'}"> <h1>Hello Angular 12</h1> <p ="{'font-size':'14px', 'font-family':'Segoe Print'}"> Angular 12 представляет модульную архитектуру приложения </p> </div>`, styles: }) export class AppComponent { }
Аналогично для установки стилей можно применять свойства объекта style:
<div ="'13px'" ="'Verdana'"> <h1>Hello Angular 12</h1> <p ="'14px'" ="'Segoe Print'"> Angular 12 представляет модульную архитектуру приложения </p> </div>
Также мы можем установить привязку
Динамическое изменение стилей
Директивы ngClass и ngStyle позволяют устанавливать привязку к выражениям, благодаря чему мы можем динамически менять стили или классы. Например:
import { Component} from '@angular/core'; @Component({ selector: 'my-app', template: `<div ="{invisible: visibility}"> <h1>Hello Angular 12</h1> <p> Angular 12 представляет модульную архитектуру приложения </p> </div> <button (click)="toggle()">Toggle</button>`, styles: }) export class AppComponent { visibility: boolean = true; // переключаем переменную toggle(){ this.visibility=!this.visibility; } }
Выражение устанавливает для класса invisible привязку к значению переменной . По нажатию на кнопку мы можем переключать это свойство,
тем самым управляя видимостью блока.
В качестве альтернативы также можно было бы использовать следующее выражение:
<div ="visibility">
Либо также можно было бы написать так:
<div ="visibility?'block':'none'">
НазадВперед
Изменения делаются чистыми функциями
Операция, инициируемая отправкой действия, будет чистой функцией, называемой в архитектуре — (редукторами).
Эти редукторы (просто чистые функции) получают действие () и состояние (), в зависимости от отправленного действия (обычно отфильтрованного оператором ), они выполняют операцию и возвращают новый объект состояния.
Преимущества использования чистых функций хорошо известны, например то что они сразу готовы к тестированию. Если вы передадите те же аргументы, то получите тот же результат.
Этот подход также позволяет нам перемещаться между различными экземплярами нашего состояния с помощью инструментов разработки и видеть, что изменилось между экземплярами, кто их изменил, и многое другое. Поэтому использование чистых функций и возвращение новых экземпляров состояния также значительно облегчает отладку.
Но главное преимущество, на мой взгляд, заключается в том, что, привязав все входные данные наших компонентов к свойствам состояния (), мы можем изменить стратегию обнаружения изменений () на , и это улучшит производительность приложения.
Пример NGRX
- Установка библиотеки
- Создание структуры папок для хранилища
- Создание хранилища и начальных значений
- Создание действий (Actions)
- Создание редукторов (Reducers)
- Создание эффектов (Effects)
- Создание селекторов (Selectors)
- Конечная настройка
- Использование хранилища в компонентах
Создание хранилища и начальных значений
- Мы создаем и экспортируем интерфейс со структурой пользовательской среды.
- Мы делаем то же самое с начальным пользовательским состоянием, которое реализует недавно созданный интерфейс.
- Состояние приложения содержит состояние пользователя и конфигурации, а также состояние маршрутизатора.
- Потом задаем начальное состояние приложения.
- Наконец, экспортирует функцию, чтобы получить начальное состояние (мы будем использовать его позже).
Создание Действий
- Мы экспортируем Enum, содержащий определение для типов действий. Таким образом, мы избегаем использования и повторения строк для использования типов действий, процесс, который может легко порождаться ошибками.
- Потом мы создаем и экспортируем класс для каждого из ваших действий. Все они должны реализовать интерфейс Action из ngrx. Наконец, мы устанавливаем тип в одно из значений перечислений, и если вам нужно полезное содержимое для действия, вы добавляете его в конструктор класса.
- Наконец, мы экспортируем тип, содержащий наши классы действий. Это обеспечит нам проверку типов, которую мы можем использовать, например, в наших редукторах.
Создание Редукторов
- Объявление редуктора получает состояние и, в этом случае, действия пользователя и возвращает IUserState.
- Используя оператор switch, мы генерируем наблюдения для каждого возможного типа действия.
- Каждый случай возвращает новый объект, который является результатом слияния старого состояния и нового значения.
- Все редукторы имеют результат по умолчанию, который просто возвращает состояние без каких-либо изменений.
Добавим Эффекты
- Мы объявляем наши пользовательские эффекты с помощью инъекционного декоратора.
- Мы объявляем наши эффекты, используя декоратор эффектов, предоставленный ngrx/Effects.
- Используя действия, предоставленные ngrx / Effects, мы собираемся запустить конвейер нашего оператора для этого эффекта.
- Следующим шагом является установка типа действия эффекта с помощью оператора ofType.
- Следующие части представляют собой операторы rxjs, которые мы используем для получения того, что нам нужно (у нас уже есть ссылка на документацию по rxjs в этой статье).
- Наконец, в последнем операторе Effect отправит еще одно действие.
- В конструкторе мы внедряем сервисы, которые мы собираемся использовать, действия для ngrx / Effects, и в этом случае также хранилище (учтите, что это демо, и мы получаем выбранного пользователя из списка пользователей в наше хранилище).
Итоговая настройка
- Мы импортируем наши редукторы и предоставляем их в forRoot модуля хранилища.
- Мы импортируем наши эффекты и предоставляем их внутри массива в модуль forRoot эффектов.
- Мы устанавливаем конфигурацию для модуля состояния маршрутизатора, предоставляющего маршрутизатор stateKey.
- И мы добавляем инструменты разработчика магазина, если среда не является производственной.
Использование хранилища в некоторых компонентах
Во-первых, давайте получим конфигурацию при запуске приложения:
- Мы добавляем хранилище в наш app.component.
- Мы устанавливаем для свойства компонента значение селектора в конфигурации, потому что хотим отобразить часть этой информации в HTML.
- В onInit мы отправляем действие, чтобы получить конфигурацию.
- Подобно тому, как мы управляем конфигурацией, мы собираемся получить список пользователей. Сначала мы внедряем хранилище в компонент пользователя.
- На onInit мы отправляем действие, чтобы получить пользователей.
- Мы создаем свойство для компонента и присваиваем ему список пользователей, используя селектор списка пользователей.
Давайте посмотрим на компонент пользовательского контейнера:
Написание бесполезных селекторов директив
Директивы Angular — мощный инструмент, позволяющий применять пользовательскую логику к различным элементам HTML. При этом также используются селекторы CSS, которые предоставляют еще больше возможностей. Для примера возьмем директиву , которая проверяет наличие ошибок в соответствующего элемента и применяет к нему определенный стиль. Допустим, мы добавляем в нее селектор атрибута . Она работает хорошо, однако теперь необходимо найти все элементы формы с атрибутом и добавить в них . Утомительная задача. Мы можем использовать селектор атрибута директивы . Директива выглядит следующим образом:
Теперь она будет автоматически связываться со всеми элементами управления формы в модуле.
Но на этом использование не заканчивается. Допустим, мы хотим применить анимацию тряски ко всем , в которых есть класс . Мы можем с легкостью написать директиву и привязать ее с помощью селектора класса: .
Используйте лучшие селекторы для директив, чтобы не загромождать HTML ненужными атрибутами.
AngularJS Applications
AngularJS modules define AngularJS applications.
AngularJS controllers control AngularJS applications.
The ng-app
directive defines the application, the ng-controller
directive defines the controller.
AngularJS Example
<div ng-app=»myApp» ng-controller=»myCtrl»>First Name: <input type=»text» ng-model=»firstName»><br>
Last Name: <input type=»text» ng-model=»lastName»><br><br>
Full Name: {{firstName + » » + lastName}}</div><script>
var app = angular.module(‘myApp’, []);app.controller(‘myCtrl’,
function($scope) { $scope.firstName= «John»; $scope.lastName= «Doe»;});</script>
AngularJS modules define applications:
var app = angular.module(‘myApp’, []);
AngularJS controllers control applications:
AngularJS Controller
app.controller(‘myCtrl’,
function($scope) { $scope.firstName= «John»;
$scope.lastName= «Doe»;});
You will learn more about modules and controllers later in this tutorial.
❮ Previous
Next ❯
Маршрутизация. Используем Route Guard
Маршрутизация позволяет сопоставлять запросы к приложению с определенными ресурсами внутри приложения. Довольно часто приходится решать задачу ограничения видимости пути, по которому располагаются определенные компоненты, в зависимости от некоторых условий. В этих случаях в Angular есть механизм ограничения перехода. В качестве примера, приведен сервис, который будет реализовывать route guard. Допустим, в приложении аутентификация пользователя реализована с использованием JWT. Упрощенный вариант сервиса, который выполняет проверку авторизован ли пользователь, можно представить в виде:
Для реализации route guard необходимо реализовать интерфейс , который состоит из единственной функции .
Реализация использует описанный выше для проверки авторизации пользователя. Метод возвращает логическое значение, которое может быть использовано в условии активации маршрута.
Теперь мы можем применить созданный Route Guard к любому маршруту или пути. Для этого при объявлении мы указываем наш сервис, наследующий интерфейс, в секции :
В этом случае маршрут имеет дополнительное конфигурационное значение . , описанный ранее передается аргументом в данное свойство . Далее метод будет вызываться каждый раз, когда кто-нибудь попытается получить доступ к пути . Если пользователь авторизован он получит доступ к пути , в противном случае он будет перенаправлен на путь .
Следует знать, что по прежнему позволяет активировать компонент по данному пути, но не позволяет перейти на него. Если нужно защитить активацию и загрузку компонента, то для такого случая можем использовать . Реализация может быть сделана по аналогии.
Популярные встроенные Angular-директивы [ править | править код ]
С помощью директив AngularJS можно создавать пользовательские HTML-теги и атрибуты, чтобы добавить поведение некоторым элементам.
ng-app Объявляет элемент корневым для приложения. ng-bind Автоматически заменяет текст HTML-элемента на значение переданного выражения. ng-model То же, что и ng-bind, только обеспечивает двустороннее связывание данных. Изменится содержимое элемента — ангуляр изменит и значение модели. Изменится значение модели — ангуляр изменит текст внутри элемента. ng-class Определяет классы для динамической загрузки. ng-controller Определяет JavaScript-контроллер для вычисления HTML-выражений в соответствии с MVC. ng-repeat Создает экземпляр DOM для каждого элемента из коллекции. ng-show и ng-hide Показывает или скрывает элемент, в зависимости от значения логического выражения. ng-switch Создаёт экземпляр шаблона из множества вариантов, в зависимости от значения выражения. ng-view Базовая директива, отвечает за обработку маршрутов , которые принимают JSON перед отображением шаблонов, управляемых указанными контроллерами. ng-if Удаляет или создаёт часть DOM-дерева в зависимости от значения выражения. Если значение выражения, назначенного ngIf, равно false, элемент удаляется из DOM, иначе — вновь клонированный элемент вставляется в DOM.
Также существует возможность создавать настраиваемые директивы, используя в том числе шаблоны в теге script.