Если вы когда-нибудь создавали директивы Angular, то вы, вероятно, использовали в качестве селектора конструкцию, в которой используются скобки:

Для того чтобы рассмотреть пример сложного селектора, взглянем на директиву
Тут стоит обратить внимание на следующее:
Под внешней ссылкой мы понимаем тег
Красота этого селектора заключается в том, что нам не нужно создавать имя атрибута для чего-то такого, что лучше всего можно описать как противоположность некоей сущности.
Мы можем, для выделения внешних ссылок, использовать что-то вроде директивы с именем
Результаты применения директивы к внешним ссылкам должны выглядеть так:
Обе эти цели достижимы благодаря использованию
Обратите внимание на то, что тут мы, кроме прочего, декорировали свойства с помощью декоратора
Ещё одна допустимая реализация подобного решения может заключаться в использовании декоратора
Подробности об этой методике можно почитать здесь.
Создадим простой навигационный блок, содержащий ссылки, ведущие на внешние ресурсы:
Если, с помощью инструментов разработчика Chrome, посмотреть соответствующий HTML-код, то можно будет увидеть следующее:

HTML-код навигационного блока после применения директивы
Это именно то, что нам нужно. Директива работает без необходимости применения дополнительных селекторов атрибутов.
Из этого материала вы узнали о том, что, при работе с директивами Angular, необязательно использовать селекторы атрибутов. Здесь мы сначала исследовали директиву
Уважаемые читатели! Если вам известны какие-нибудь неочевидные приёмы разработки веб-проектов с использованием Angular — просим о них рассказать.
([])
. Такой подход, хотя чаще всего применяется именно он, не является единственно возможным. На самом деле, селекторы, используемые в директивах, дают программисту широкий простор для творчества. Для того чтобы продемонстрировать эту идею в действии, в материале, перевод которого мы публикуем сегодня, рассмотрена методика создания директивы, предназначенной для работы с внешними ссылками, которые имеются в шаблоне. В частности, речь пойдёт о том, как можно находить обычные HTML-элементы, и, при необходимости, исключать из выборки некоторые из них, используя псевдокласс :not
.
Директива ngForm
Для того чтобы рассмотреть пример сложного селектора, взглянем на директиву
ngForm
:@Directive({
selector: 'form:not([ngNoForm]):not([formGroup]),ngForm,ng-form,[ngForm]',
})
Тут стоит обратить внимание на следующее:
- Директива может быть рассчитана на несколько селекторов, которые можно перечислять через запятую.
- Здесь можно смешивать целевые HTML-элементы (наподобие
<form>
) c HTML-атрибутами (вродеngForm
). - Для исключения каких-то элементов из выборки можно использовать псевдокласс
:not
.
Создание директивы для работы с внешними ссылками
Под внешней ссылкой мы понимаем тег
<a>
, у которого нет директивы routerLink
. Учитывая то, что мы выяснили, анализируя предыдущий пример, соответствующий селектор можно описать так:@Directive({
selector: 'a:not([routerLink])',
})
Красота этого селектора заключается в том, что нам не нужно создавать имя атрибута для чего-то такого, что лучше всего можно описать как противоположность некоей сущности.
Мы можем, для выделения внешних ссылок, использовать что-то вроде директивы с именем
externalLink
, но это совершенно не нужно, так как такой подход выливается в дублирование уже существующих механизмов. Кроме того, легко забыть добавить подобную директиву к некоторым внешним ссылкам. Сильная сторона нашего метода заключается в том, что мы, благодаря одной строке, можем обращаться ко всем внешним ссылкам.Результаты применения директивы к внешним ссылкам должны выглядеть так:
- Ссылка должна открываться в отдельном окне.
- К ссылке должен быть добавлен добавить атрибут
rel
, что позволит улучшить производительность и повысить безопасность решения.
Обе эти цели достижимы благодаря использованию
@HostBinding()
:@Directive({
selector: 'a:not([routerLink])'
})
export class ExternalLinkDirective {
@HostBinding('rel')
@Input()
rel = 'noopener';
@HostBinding('target')
@Input()
target = '_blank';
}
Обратите внимание на то, что тут мы, кроме прочего, декорировали свойства с помощью декоратора
@Input()
, что, при необходимости, открывает возможности для переопределения.Ещё одна допустимая реализация подобного решения может заключаться в использовании декоратора
@Attribute()
. Такой подход даст небольшое увеличение в производительности, так как, в отличие от декоратора @Input()
, при использовании @Attribute()
значения соответствующих свойств вычисляются лишь один раз, то есть, не производится постоянной проверки свойств rel
и target
в цикле проверки изменений.Подробности об этой методике можно почитать здесь.
Тестирование директивы
Создадим простой навигационный блок, содержащий ссылки, ведущие на внешние ресурсы:
<nav>
<a href="https://google.com">Google</a>
<a href="https://bing.com">Bing</a>
<a href="https://forbes.com">Forbes</a>
</nav>
Если, с помощью инструментов разработчика Chrome, посмотреть соответствующий HTML-код, то можно будет увидеть следующее:

HTML-код навигационного блока после применения директивы
Это именно то, что нам нужно. Директива работает без необходимости применения дополнительных селекторов атрибутов.
Итоги
Из этого материала вы узнали о том, что, при работе с директивами Angular, необязательно использовать селекторы атрибутов. Здесь мы сначала исследовали директиву
ngForm
, после чего использовали полученные знания для создания собственной директивы, предназначенной для работы с внешними ссылками. Надеемся, эта методика вам пригодится.Уважаемые читатели! Если вам известны какие-нибудь неочевидные приёмы разработки веб-проектов с использованием Angular — просим о них рассказать.

Комментарии (3)
supersmeh
31.08.2018 13:57Я один раз такое только применил для заглушки против двойных кликов. Вот в таком случае очень удобно получилось ( у нас договоренность, что все кнопки только тэг a class=«btn»)
@Directive({ selector: 'a.btn' }) export class NoDblClick { constructor() { } @HostListener('click', ['$event']) clickEvent(event: MouseEvent) { let element: any = event.target; if (!element) { return; } element.classList.add('btn-freeze'); setTimeout(function () { element.classList.remove('btn-freeze'); }, 500); } }
AxisPod
С одной стороны это гибко. С другой стороны тип данной функциональности: Счастливой отладки.
Сколько новый разработчик будет искать почему так карёжатся ссылки? И хоть это гибко, я против подобных решений.
Я конечно понимаю стандартное поведение для NgForm, но вот своё подобное всё же я не стал бы делать.
Nimtar
А если использовать какой-нибудь атрибут-комментарий?
Я полагаю, можно сделать с помощью чего-то подобного:
Это в принципе реализуемо? Какие недостатки и преимущества у подхода? Разумеется, при наличии предварительной договорённости в команде/сообществе.