15 Angular директив на каждый день
Пользовательские директивы (Custom Directives) - мощная функция в Angular, которая позволяет расширять функциональность HTML-элементов. Они предоставляют возможность создавать повторно используемые компоненты, добавлять функциональность к существующим элементам и улучшать модульность и поддерживаемость вашего приложения на Angular. В этой статье мы рассмотрим пользовательские директивы в Angular и предоставим 15 примеров из реального мира, чтобы помочь вам овладеть этой важной концепцией.
Что это такое Angular Custom Directives?
Angular Custom Directives используются для создания повторно используемых компонентов и добавления специфических функциональностей к элементам HTML. Они определяются с использованием декоратора @Directive
, который принимает объект с опциями метаданных. Эти опции включают селектор, входные и выходные параметры и логику директивы.
Вот пример базовая структура кастомной директивы в Angular:
import { Directive, Input, ElementRef, HostListener } from '@angular/core';
@Directive({
selector: '[appCustomDirective]'
})
export class CustomDirective {
@Input() appCustomDirective: string;
constructor(private el: ElementRef) {}
@HostListener('mouseenter') onMouseEnter() {
this.el.nativeElement.style.backgroundColor = this.appCustomDirective;
}
@HostListener('mouseleave') onMouseLeave() {
this.el.nativeElement.style.backgroundColor = null;
}
}
В этом примере мы создали пользовательскую директиву с именем appCustomDirective. Она изменяет цвет фона элемента, к которому она применяется, когда указатель мыши входит или выходит из него.
Чтобы за использовать нашу пользовательскую директиву, вам необходимо добавить ее в массив declarations вашего модуля Angular. Вы можете применить директиву к элементу, используя селектор директивы в качестве атрибута в вашем HTML-шаблоне.
<div appCustomDirective="lightblue">Hover over me!</div>
15 примеров пользовательских директив на каждый день
- Пользовательская директива валидации: Директива для пользовательской валидации формы.
- Директива Autofocus: Автоматически устанавливает фокус на поле ввода при загрузке страницы.
- Директива Lazy Load Images: Ленивая загрузка изображения.
- Директива Drag-and-Drop: Реализовывает функциональность Drag-and-Drop элементов.
- Директива Ellipsis: Добавляет многоточие к тексту, который выходит за границы контейнера.
- Директива Click Outside: Закрывает выпадающий список или модальное окно при щелчке вне его области.
- Директива Confirm Dialog: Создает диалоговое окно подтверждения действий.
- Директива Infinite Scroll: Реализует бесконечную прокрутку для длинных списков.
- Директива Highlight Search Results: Выделяет совпадения поискового запроса в результатах поиска.
- Директива Responsive: Показывает или скрывает элементы в зависимости от размера экрана.
- Директива Input Mask: Форматирует значения ввода в момент набора.
- Директива Tooltip: Отображает подсказки на элементах с дополнительной информацией.
- Директива Disable Right-Click: Запрещает правый клик на элементах.
- Директива TimeAgo: Отображает время, прошедшее с определенной даты.
- Директива Copy to Clipboard: Позволяет пользователям копировать текст в буфер обмена одним щелчком.
Custom Validation Directive
Angular позволяет создавать собственную пользовательскую директиву валидации и реализовать свою логику валидации для элементов управления формы. В этом примере мы создадим пользовательскую директиву валидации, чтобы проверить, содержит ли пароль буквы и цифры. Если пароль не соответствует этим критериям, мы пометим элемент управления формы как недопустимый и отобразим сообщение об ошибке. Вот как можно создать эту пользовательскую директиву валидации:
Создание директивы:
ng generate directive password-validator
Реализуем Validation Directive:
import { Directive, Input } from '@angular/core';
import { NG_VALIDATORS, Validator, AbstractControl, ValidationErrors } from '@angular/forms';
@Directive({
selector: '[appPasswordValidator]',
providers: [
{
provide: NG_VALIDATORS,
useExisting: PasswordValidatorDirective,
multi: true,
},
],
})
export class PasswordValidatorDirective implements Validator {
@Input('appPasswordValidator') requiredPattern: string;
validate(control: AbstractControl): ValidationErrors | null {
if (control.value) {
const pattern = new RegExp(this.requiredPattern);
const isValid = pattern.test(control.value);
if (!isValid) {
return { passwordPattern: true };
}
}
return null;
}
}
В данном коде мы создаем кастомную директиву с именем PasswordValidatorDirective
. Она реализует интерфейс Validator
и предоставляет метод validate
. Этот метод вызывается при валидации элемента управления формы.
Использование Custom Validation Directive в шаблоне:
Допустим, что у вас есть форма Angular, вы можете использовать директиву appPasswordValidator
на поле ввода, чтобы валидировать пароль.
<input
type="password"
name="password"
[(ngModel)]="user.password"
#password="ngModel"
appPasswordValidator="[A-Za-z]+[0-9]+"
required
/>
<div *ngIf="password.invalid && (password.dirty || password.touched)">
<div *ngIf="password.hasError('required')">Password is required.</div>
<div *ngIf="password.hasError('passwordPattern')">Password must contain letters and numbers.</div>
</div>
Отображение ошибок валидации:
Мы используем template-driven формы Angular для привязки поля ввода к директиве ngModel
. Когда пользователь взаимодействует с полем ввода, ошибки валидации отображаются на основе ошибки passwordPattern
, возвращаемой методом validate
нашей директивы.
Autofocus Directive
Создание пользовательской директивы autofocus в Angular позволяет автоматически установить фокус на поле ввода при загрузке страницы. В этом примере мы создадим пользовательскую директиву с названием appAutofocus
, чтобы автоматически перевести фокус на примененный к нему элемент при загрузке страницы. Вот как вы можете реализовать эту директиву:
Создание директивы:
В первую очередь, создайте новую директиву с помощью Angular CLI:
ng generate directive autofocus
Реализуем директиву Autofocus:
Откройте файл autofocus.directive.ts, созданный Angular CLI, и внесите следующие изменения:
import { Directive, ElementRef, AfterViewInit } from '@angular/core';
@Directive({
selector: '[appAutofocus]'
})
export class AutofocusDirective implements AfterViewInit {
constructor(private el: ElementRef) {}
ngAfterViewInit() {
this.el.nativeElement.focus();
}
}
В этом коде мы создаем пользовательскую директиву с названием AutofocusDirective
. Она реализует хук жизненного цикла AfterViewInit
, который позволяет нам установить фокус на элементе после инициализации представления.
Подкючаем Autofocus Directive в шаблоне:
Теперь вы можете использовать директиву appAutofocus
на любом HTML-элементе, чтобы автоматически установить фокус на нем при загрузке страницы.
<input type="text" placeholder="Auto-focused input" appAutofocus />
В этом примере мы применяем директиву appAutofocus
к элементу input. При загрузке страницы, данное поле ввода автоматически получает фокус, что удобно для пользователя, чтобы сразу начать вводить текст.
Lazy Load Images Directive
Создание пользовательской директивы в Angular для ленивой загрузки изображений может помочь улучшить производительность и пользовательский опыт вашего веб-сайта, загружая изображения только когда они видимы на экране. В этом примере мы создадим пользовательскую директиву с названием appLazyLoad
для реализации ленивой загрузки изображений.
Создание директивы:
Создадим новую директиву с помощью Angular CLI:
ng generate directive lazy-load
Реализуем директиву Lazy Load Images:
Откройте файл lazy-load.directive.ts, созданный Angular CLI, и измените его следующим образом:
import { Directive, ElementRef, HostListener, Renderer2 } from '@angular/core';
@Directive({
selector: '[appLazyLoad]'
})
export class LazyLoadDirective {
constructor(private el: ElementRef, private renderer: Renderer2) {}
@HostListener('window:scroll', ['$event'])
onScroll() {
if (this.isElementInViewport()) {
this.loadImage();
}
}
private isElementInViewport(): boolean {
const rect = this.el.nativeElement.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
}
private loadImage() {
const dataSrc = this.el.nativeElement.getAttribute('data-src');
if (dataSrc) {
this.renderer.setAttribute(this.el.nativeElement, 'src', dataSrc);
this.el.nativeElement.removeAttribute('data-src');
}
}
}
В этом коде мы создаем пользовательскую директиву под названием LazyLoadDirective
. Директива прослушивает событие window:scroll
, и когда элемент попадает в область видимости, загружает изображение, заменяя атрибут data-src
атрибутом src.
Подкючаем директиву Lazy Load Images в шаблоне:
Для применения директивы appLazyLoad
к элементу img
используйте атрибут data-src
, чтобы указать источник изображения. Атрибут src
будет установлен динамически, когда изображение будет видимым в окне просмотра (viewport).
<img
src="placeholder.jpg"
data-src="lazy-image.jpg"
alt="Lazy-loaded image"
appLazyLoad
/>
В этом примере мы устанавливаем атрибут data-src
в URL изображения, которое вы хотите загрузить лениво. Атрибут src
сначала устанавливается на изображение-заглушку или спиннер загрузки.
Drag-and-Drop Directive
Создание пользовательской директивы Drag-and-Drop в Angular позволяет пользователям взаимодействовать с элементами на вашей странице. В этом примере мы создадим пользовательскую директиву с именем appDraggable
для Drag-and-Drop элементов.
Создание директивы:
Создадим новую директиву с помощью Angular CLI:
ng generate directive draggable
Реализуем директиву Drag-and-Drop:
Откройте файл draggable.directive.ts
, сгенерированный Angular CLI, и внесите следующие изменения:
import { Directive, ElementRef, HostListener, Renderer2 } from '@angular/core';
@Directive({
selector: '[appDraggable]'
})
export class DraggableDirective {
private isDragging = false;
constructor(private el: ElementRef, private renderer: Renderer2) {
this.renderer.setStyle(this.el.nativeElement, 'cursor', 'grab');
this.renderer.setStyle(this.el.nativeElement, 'user-drag', 'none');
}
@HostListener('mousedown', ['$event'])
onMouseDown(event: MouseEvent) {
this.isDragging = true;
this.renderer.setStyle(this.el.nativeElement, 'cursor', 'grabbing');
event.preventDefault();
}
@HostListener('document:mouseup')
onMouseUp() {
if (this.isDragging) {
this.isDragging = false;
this.renderer.setStyle(this.el.nativeElement, 'cursor', 'grab');
}
}
@HostListener('document:mousemove', ['$event'])
onMouseMove(event: MouseEvent) {
if (this.isDragging) {
const offsetX = event.clientX - this.el.nativeElement.getBoundingClientRect().left;
const offsetY = event.clientY - this.el.nativeElement.getBoundingClientRect().top;
this.renderer.setStyle(this.el.nativeElement, 'position', 'absolute');
this.renderer.setStyle(this.el.nativeElement, 'left', `${offsetX}px`);
this.renderer.setStyle(this.el.nativeElement, 'top', `${offsetY}px`);
}
}
}
В этом коде мы создаем пользовательскую директиву под названием DraggableDirective
. Данная директива позволяет добавить функциональность перетаскивания для примененного к ней элементу. Она отслеживает события мыши, позволяя пользователю кликать, перетаскивать и отпускать элемент.
Подкючаем директиву Drag-and-Drop в шаблоне:
Чтобы применить директиву appDraggable
к элементу, добавьте ее в качестве атрибута:
<div appDraggable>
Drag me around!
</div>
В этом примере мы применили директиву appDraggable
к элементу div
. Пользователи могут щелкнуть по элементу и перемещать его по странице.
Ellipsis Directive
Создание пользовательской директивы в Angular для добавления троеточия к тексту, который выходит за пределы своего контейнера, поможет улучшить читаемость и эстетику пользовательского интерфейса. В этом примере мы создадим пользовательскую директиву с именем appEllipsis
, чтобы добавить троеточие к тексту, который превышает ширину своего контейнера.
Создание директивы:
Создадим новую директиву с помощью Angular CLI:
ng generate directive ellipsis
Реализуем директиву Drag-and-Drop:
Откройте файл ellipsis.directive.ts
, созданный Angular CLI, и измените его следующим образом:
import { Directive, ElementRef, Renderer2, AfterViewInit } from '@angular/core';
@Directive({
selector: '[appEllipsis]'
})
export class EllipsisDirective implements AfterViewInit {
constructor(private el: ElementRef, private renderer: Renderer2) {}
ngAfterViewInit() {
const container = this.el.nativeElement;
const content = container.innerHTML;
if (container.scrollWidth > container.clientWidth) {
this.renderer.setAttribute(container, 'title', content);
this.renderer.setStyle(container, 'white-space', 'nowrap');
this.renderer.setStyle(container, 'overflow', 'hidden');
this.renderer.setStyle(container, 'text-overflow', 'ellipsis');
}
}
}
В этом коде мы создаем пользовательскую директиву с именем EllipsisDirective
. Данная директива автоматически добавляет многоточие к тексту, который выходит за пределы ширины контейнера, устанавливая CSS свойства white-space
, overflow
и text-overflow
.
Подкючаем директиву Ellipsis в шаблоне:
Чтобы применить директиву appEllipsis
к элементу, содержащему текст, добавьте ее как атрибут:
<div appEllipsis>
This is a long text that will be truncated with an ellipsis if it overflows its container.
</div>
В этом примере мы применили директиву appEllipsis
к элементу div
. Если текст выходит за границы div
, директива добавит многоточие и всплывающую подсказку с полным текстом при наведении пользователем на элемент.
Click Outside Directive
Создание пользовательской директивы в Angular для обработки кликов за пределами элемента, таких как выпадающий список или модальное окно, может улучшить юзабилити, позволяя закрывать эти элементы, когда пользователи взаимодействуют с остальной частью страницы. В этом примере мы создадим пользовательскую директиву с именем appClickOutside
, чтобы закрыть выпадающий список, когда пользователи кликают за его пределами.
Создание директивы:
Создадим новую директиву с помощью Angular CLI:
ng generate directive click-outside
Реализуем директиву Click Outside:
Откройте файл click-outside.directive.ts
, созданный Angular CLI, и измените его следующим образом:
import { Directive, ElementRef, Output, EventEmitter, HostListener } from '@angular/core';
@Directive({
selector: '[appClickOutside]'
})
export class ClickOutsideDirective {
@Output() appClickOutside = new EventEmitter();
constructor(private el: ElementRef) {}
@HostListener('document:click', ['$event'])
onClick(event: Event): void {
if (!this.el.nativeElement.contains(event.target)) {
this.appClickOutside.emit();
}
}
}
В данном коде мы создаем пользовательскую директиву с именем ClickOutsideDirective
. Она отслеживает клики по документу, и если цель клика находится за пределами элемента, к которому применена директива, она генерирует событие appClickOutside
.
Подкючаем директиву Click Outside в шаблоне:
Чтобы применить директиву appClickOutside
к элементу выпадающего списка или модального окна, добавьте ее в качестве атрибута.
<div appClickOutside (appClickOutside)="closeDropdown()">
<button (click)="toggleDropdown()">Toggle Dropdown</button>
<div *ngIf="dropdownOpen" class="dropdown">
Dropdown content
</div>
</div>
В этом примере мы применили директиву appClickOutside
к элементу div
, содержащему выпадающий список. Привязка события (appClickOutside)="closeDropdown()"
вызовет метод closeDropdown
при клике за пределами div
.
Confirm Dialog Directive
Создание пользовательской директивы в Angular для реализации диалогового окна подтверждения может помочь вам стандартизировать и упростить процесс подтверждения действий перед их выполнением, например, удаление элементов или совершение непрерываемых изменений. В этом примере мы создадим пользовательскую директиву с именем appConfirmDialog
для открытия диалогового окна подтверждения перед выполнением действия.
Создание директивы:
Создадим новую директиву с помощью Angular CLI:
ng generate directive confirm-dialog
Реализуем директиву Confirm Dialog:
Откройте файл confirm-dialog.directive.ts
, созданный Angular CLI, и измените его следующим образом:
import { Directive, Input, TemplateRef, ViewContainerRef, HostListener } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ConfirmDialogComponent } from './confirm-dialog/confirm-dialog.component'; // Make sure to import your confirmation dialog component
@Directive({
selector: '[appConfirmDialog]'
})
export class ConfirmDialogDirective {
@Input() confirmMessage: string;
constructor(
private dialog: MatDialog,
private templateRef: TemplateRef,
private viewContainer: ViewContainerRef
) {}
@HostListener('click', ['$event'])
onClick(event: Event): void {
event.preventDefault();
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
data: { message: this.confirmMessage }
});
dialogRef.afterClosed().subscribe((result) => {
if (result) {
this.viewContainer.createEmbeddedView(this.templateRef);
}
});
}
}
В этом коде мы создаем пользовательскую директиву с именем ConfirmDialogDirective
. Она прослушивает события клика, открывает диалоговое окно подтверждения с использованием диалога Angular Material и выполняет действие, указанное в шаблоне директивы, если пользователь подтверждает.
Подкючаем директиву Confirm Dialog в шаблоне:
Чтобы применить директиву appConfirmDialog
к кнопке или любому другому кликабельному элементу, добавьте ее в качестве атрибута и предоставьте сообщение подтверждения.
<button [appConfirmDialog]="'Are you sure you want to perform this action?'">Delete</button>
В этом примере мы применили директиву appConfirmDialog
к кнопке. При нажатии на кнопку появится диалоговое окно подтверждения с предоставленным сообщением. Действие будет выполнено только в случае подтверждения пользователем.
Infinite Scroll Directive
Создание пользовательской директивы в Angular для реализации бесконечной прокрутки может значительно улучшить пользовательский опыт, особенно при работе с длинными списками данных. В этом примере мы создадим пользовательскую директиву с именем appInfiniteScroll
, чтобы загружать дополнительный контент по мере прокрутки пользователя вниз по странице.
Создание директивы:
Создадим новую директиву с помощью Angular CLI:
ng generate directive infinite-scroll
Реализуем директиву Infinite Scroll:
Откройте файл infinite-scroll.directive.ts
, созданный Angular CLI, и измените его следующим образом:
import { Directive, ElementRef, HostListener, Input, Output, EventEmitter } from '@angular/core';
@Directive({
selector: '[appInfiniteScroll]'
})
export class InfiniteScrollDirective {
@Input() scrollThreshold = 100;
@Output() scrolled = new EventEmitter();
constructor(private el: ElementRef) {}
@HostListener('scroll', ['$event'])
onScroll(event: Event): void {
const element = event.target as HTMLElement;
const atBottom = element.scrollHeight - element.scrollTop <= element.clientHeight + this.scrollThreshold;
if (atBottom) {
this.scrolled.emit();
}
}
}
В этом коде мы создаем пользовательскую директиву с именем InfiniteScrollDirective
. Она отслеживает события прокрутки на примененном к нему элементе и, когда пользователь достигает нижней точки прокрутки (в пределах определенного порога), генерирует событие scrolled
.
Подкючаем директиву Infinite Scroll в шаблоне:
Для применения директивы appInfiniteScroll
к контейнеру со скроллированием, добавьте ее в виде атрибута и укажите привязку события (scrolled
):
<div class="scrollable-content" appInfiniteScroll (scrolled)="loadMoreData()">
<!-- Your list of items -->
</div>
В данном примере мы применили директиву appInfiniteScroll
к прокручиваемому блоку div
. Когда пользователь прокручивает до нижней части блока, вызывается функция loadMoreData()
, обычно для получения и добавления дополнительных данных в список.
Highlight Search Results Directive
Создание пользовательской директивы в Angular для выделения результатов поиска внутри блока текста может улучшить пользовательский опыт при поиске определенных терминов в вашем приложении. В этом примере мы создадим пользовательскую директиву с именем appHighlightSearch
для выделения результатов поиска в блоке текста.
Создание директивы:
Создадим новую директиву с помощью Angular CLI:
ng generate directive highlight-search
Реализуем директиву Highlight Search Results:
Откройте файл highlight-search.directive.ts
, созданный Angular CLI, и измените его следующим образом:
import { Directive, ElementRef, Input, OnChanges } from '@angular/core';
@Directive({
selector: '[appHighlightSearch]'
})
export class HighlightSearchDirective implements OnChanges {
@Input() searchQuery: string;
constructor(private el: ElementRef) {}
ngOnChanges() {
if (this.searchQuery && this.searchQuery.length > 0) {
const text = this.el.nativeElement.innerText;
const regex = new RegExp(`(${this.escapeRegExp(this.searchQuery)})`, 'gi');
const highlightedText = text.replace(regex, '$1');
this.el.nativeElement.innerHTML = highlightedText;
}
}
private escapeRegExp(query: string): string {
return query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}
}
В этом коде мы создаем пользовательскую директиву с именем HighlightSearchDirective
. Она прослушивает изменения во входном параметре searchQuery и выделяет результаты поиска в текстовом содержимом элемента с помощью HTML-элемента <mark>
.
Подкючаем директиву Highlight Search Results в шаблоне:
Чтобы применить директиву appHighlightSearch
к элементу, содержащему текст, добавьте ее в качестве атрибута и укажите входной параметр searchQuery
.
<p [appHighlightSearch]="searchQuery">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed quisquam iste, qui ex ea voluptate velit
</p>
В этом примере мы применили директиву appHighlightSearch
к элементу p
. Входной параметр searchQuery
связан с поисковым запросом, который вы хотите выделить в тексте.
Responsive Directive
Создание пользовательской директивы в Angular для управления видимостью элементов в зависимости от размера экрана поможет вам создать отзывчивый дизайн. В этом примере мы создадим пользовательскую директиву с именем appResponsive
, чтобы показывать или скрывать элементы в зависимости от размера экрана.
Создание директивы:
Создадим новую директиву с помощью Angular CLI:
ng generate directive responsive
Реализуем директиву Responsive:
Откройте файл responsive.directive.ts
, созданный Angular CLI, и измените его следующим образом:
import { Directive, Input, OnInit, TemplateRef, ViewContainerRef } from '@angular/core';
@Directive({
selector: '[appResponsive]'
})
export class ResponsiveDirective implements OnInit {
@Input() appResponsive: string; // Comma-separated screen size breakpoints (e.g., 'md, lg')
private currentScreenWidth: string = 'md'; // Default screen size
constructor(
private templateRef: TemplateRef,
private viewContainer: ViewContainerRef
) {}
ngOnInit() {
this.detectScreenSize();
}
private detectScreenSize() {
const screenWidth = this.getScreenWidth();
if (this.appResponsive.includes(screenWidth)) {
this.viewContainer.createEmbeddedView(this.templateRef);
} else {
this.viewContainer.clear();
}
}
private getScreenWidth(): string {
const width = window.innerWidth;
if (width >= 1200) {
return 'lg';
} else if (width >= 992) {
return 'md';
} else if (width >= 768) {
return 'sm';
} else {
return 'xs';
}
}
}
В данном коде мы создаем пользовательскую директиву с именем ResponsiveDirective
. Она отслеживает изменения размера экрана и условно отображает элемент на основе предоставленных точек разрыва во входных данных appResponsive.
Подкючаем директиву Responsive в шаблоне:
Чтобы применить директиву appResponsive
к элементу, добавьте ее как атрибут и укажите требуемые точки разрыва размера экрана:
<div [appResponsive]="'md, lg'">
This content is visible on medium and large screens.
</div>
В этом примере мы применили директиву appResponsive
к элементу div
. Содержимое внутри div
будет видимым на средних (md) и больших (lg) экранах.
Input Mask Directive
Создание пользовательской директивы в Angular для применения маски ввода может помочь гарантировать, что пользователи вводят данные в определенном формате. В этом примере мы создадим пользовательскую директиву с именем appInputMask
для форматирования и проверки ввода в виде номера телефона.
Создание директивы:
Создадим новую директиву с помощью Angular CLI:
ng generate directive input-mask
Реализуем директиву Input Mask:
Откройте файл input-mask.directive.ts
, созданный Angular CLI, и измените его следующим образом:
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
selector: '[appInputMask]'
})
export class InputMaskDirective {
@Input() appInputMask: string = '';
constructor(private el: ElementRef) {}
@HostListener('input', ['$event']) onInput(event: InputEvent) {
const input = event.target as HTMLInputElement;
const originalValue = input.value.replace(/\D/g, '');
let maskedValue = '';
let valueIndex = 0;
for (let maskIndex = 0; maskIndex < this.appInputMask.length; maskIndex++) {
if (/\d/.test(this.appInputMask[maskIndex])) {
if (originalValue[valueIndex]) {
maskedValue += originalValue[valueIndex++];
} else {
break;
}
} else {
maskedValue += this.appInputMask[maskIndex];
}
}
input.value = maskedValue;
}
}
В этом коде мы создаем пользовательскую директиву с именем InputMaskDirective
. Она прослушивает события ввода и форматирует значение ввода на основе предоставленного входного параметра appInputMask
, который определяет желаемую маску.
Подкючаем директиву Input Mask в шаблоне:
Для применения директивы appInputMask
к элементу input
добавьте ее в качестве атрибута и укажите маску ввода:
<input type="text" [appInputMask]="'(999) 999-9999'">
В этом примере нам потребовалось применить директиву appInputMask
к элементу input
. Указанная маска ввода будет форматировать введенное значение как номер телефона, например, (123) 456-7890.
Tooltip Directive
Создание пользовательской директивы в Angular для отображения всплывающих подсказок может улучшить пользовательский интерфейс, предоставляя дополнительную информацию при взаимодействии пользователей с определенными элементами. В этом примере мы создадим пользовательскую директиву с названием appTooltip
для показа всплывающих подсказок при наведении мыши.
Создание директивы:
Создадим новую директиву с помощью Angular CLI:
ng generate directive tooltip
Реализуем директиву Tooltip:
Откройте файл tooltip.directive.ts
, созданный Angular CLI, и измените его следующим образом:
import { Directive, Input, HostListener, ElementRef, Renderer2, OnInit } from '@angular/core';
@Directive({
selector: '[appTooltip]'
})
export class TooltipDirective implements OnInit {
@Input() appTooltip: string;
private tooltipElement: HTMLDivElement;
private isVisible: boolean = false;
constructor(private el: ElementRef, private renderer: Renderer2) {}
ngOnInit() {
this.createTooltipElement();
}
@HostListener('mouseenter')
onMouseEnter() {
this.showTooltip();
}
@HostListener('mouseleave')
onMouseLeave() {
this.hideTooltip();
}
private createTooltipElement() {
this.tooltipElement = this.renderer.createElement('div');
this.renderer.addClass(this.tooltipElement, 'tooltip');
this.tooltipElement.innerHTML = this.appTooltip;
this.renderer.setStyle(this.tooltipElement, 'display', 'none');
this.renderer.appendChild(this.el.nativeElement, this.tooltipElement);
}
private showTooltip() {
const rect = this.el.nativeElement.getBoundingClientRect();
const top = rect.top - this.tooltipElement.clientHeight - 10;
const left = rect.left + rect.width / 2 - this.tooltipElement.clientWidth / 2;
this.renderer.setStyle(this.tooltipElement, 'top', `${top}px`);
this.renderer.setStyle(this.tooltipElement, 'left', `${left}px`);
this.renderer.setStyle(this.tooltipElement, 'display', 'block');
this.isVisible = true;
}
private hideTooltip() {
this.renderer.setStyle(this.tooltipElement, 'display', 'none');
this.isVisible = false;
}
}
В этом коде мы создаем пользовательскую директиву с названием TooltipDirective
. Она прослушивает события mouseenter
и mouseleave
и отображает или скрывает элемент всплывающей подсказки на основе входного параметра appTooltip
.
Подкючаем директиву Tooltip в шаблоне:
Для применения директивы appTooltip
к элементу добавьте ее в качестве атрибута и укажите текст подсказки:
<button [appTooltip]="'Click me to learn more'">Learn More</button>
В данном примере мы применили директиву appTooltip
к элементу кнопки. Когда пользователи наводят указатель мыши на кнопку, отображается всплывающая подсказка с указанным текстом.
Disable Right-Click Directive
Создание пользовательской директивы в Angular для отключения правого щелчка может быть полезным в ситуациях, когда вы хотите предотвратить доступ пользователей к контекстным меню или выполнение определенных действий с помощью правой кнопки мыши. В данном примере мы создадим пользовательскую директиву с именем appDisableRightClick
, чтобы запретить правый щелчок на элементах.
Создание директивы:
Создадим новую директиву с помощью Angular CLI:
ng generate directive disable-right-click
Реализуем директиву Disable Right-Click:
Откройте файл disable-right-click.directive.ts
, созданный Angular CLI, и измените его следующим образом:
import { Directive, HostListener } from '@angular/core';
@Directive({
selector: '[appDisableRightClick]'
})
export class DisableRightClickDirective {
constructor() {}
@HostListener('contextmenu', ['$event'])
onRightClick(event: Event): void {
event.preventDefault();
}
}
В данном коде мы создаем пользовательскую директиву с именем DisableRightClickDirective. Она прослушивает событие contextmenu (правый щелчок) и предотвращает стандартное поведение - отображение контекстного меню.
Подкючаем директиву Disable Right-Click в шаблоне:
Для применения директивы appDisableRightClick к элементу, добавьте ее в качестве атрибута.
<div appDisableRightClick>
Right-clicking is disabled on this element.
</div>
В этом примере мы применили директиву appDisableRightClick к элементу div. Щелчок правой кнопкой мыши на этом элементе будет отключен.
TimeAgo Directive
Создание пользовательской директивы в Angular для отображения времени в формате "time ago" (относительное время) может быть полезным для показа, сколько времени прошло с момента события. В этом примере мы создадим пользовательскую директиву с именем appTimeAgo
для отображения разницы во времени в удобном для пользователя формате.
Создание директивы:
Создадим новую директиву с помощью Angular CLI:
ng generate directive time-ago
Реализуем директиву TimeAgo:
Откройте файл time-ago.directive.ts
, созданный Angular CLI, и измените его следующим образом:
import { Directive, Input, ElementRef, Renderer2, OnChanges, SimpleChanges } from '@angular/core';
@Directive({
selector: '[appTimeAgo]'
})
export class TimeAgoDirective implements OnChanges {
@Input() appTimeAgo: Date;
constructor(private el: ElementRef, private renderer: Renderer2) {}
ngOnChanges(changes: SimpleChanges): void {
if (changes.appTimeAgo) {
this.updateTimeAgo();
}
}
private updateTimeAgo(): void {
if (this.appTimeAgo instanceof Date) {
const timeDifference = Date.now() - this.appTimeAgo.getTime();
const secondsAgo = Math.floor(timeDifference / 1000);
let text: string;
if (secondsAgo < 60) {
text = 'just now';
} else if (secondsAgo < 3600) {
const minutes = Math.floor(secondsAgo / 60);
text = `${minutes} minute${minutes > 1 ? 's' : ''} ago`;
} else if (secondsAgo < 86400) {
const hours = Math.floor(secondsAgo / 3600);
text = `${hours} hour${hours > 1 ? 's' : ''} ago`;
} else {
const days = Math.floor(secondsAgo / 86400);
text = `${days} day${days > 1 ? 's' : ''} ago`;
}
this.renderer.setProperty(this.el.nativeElement, 'textContent', text);
}
}
}
В этом коде мы создаем пользовательскую директиву с именем TimeAgoDirective
. Она отслеживает изменения входного параметра appTimeAgo
, который должен быть объектом JavaScript Date
, и обновляет содержимое текста элемента для отображения относительной разницы во времени.
Подкючаем директиву TimeAgo в шаблоне:
Чтобы применить директиву appTimeAgo к элементу, добавьте ее как атрибут и привяжите входной параметр appTimeAgo к объекту типа Date.
<p [appTimeAgo]="postDate">
В этом примере мы применили директиву appTimeAgo
к элементу p
, и привязали свойство postDate
к входному параметру appTimeAgo
. Директива будет отображать относительную разницу во времени между текущим временем и указанной postDate
.
Copy to Clipboard Directive
Создание пользовательской директивы в Angular, позволяющей пользователям копировать содержимое в буфер обмена, может улучшить удобство использования вашего приложения. В этом примере мы создадим пользовательскую директиву с именем appCopyToClipboard
, чтобы пользователи могли копировать текст при щелчке по элементу.
Создание директивы:
Создадим новую директиву с помощью Angular CLI:
ng generate directive copy-to-clipboard
Реализуем директиву Copy to Clipboard:
Откройте файл copy-to-clipboard.directive.ts
, созданный Angular CLI, и измените его следующим образом:
import { Directive, Input, ElementRef, HostListener } from '@angular/core';
@Directive({
selector: '[appCopyToClipboard]'
})
export class CopyToClipboardDirective {
@Input() appCopyToClipboard: string;
constructor(private el: ElementRef) {}
@HostListener('click')
onClick() {
if (this.appCopyToClipboard) {
const textarea = document.createElement('textarea');
textarea.value = this.appCopyToClipboard;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
}
}
}
В этом коде мы создаем пользовательскую директиву с именем CopyToClipboardDirective
. Она прослушивает события щелчка по элементу, к которому применяется, создает временный элемент textarea
, копирует содержимое и удаляет элемент textarea
из DOM
.
Подкючаем директиву Copy to Clipboard в шаблоне:
Чтобы применить директиву appCopyToClipboard
к элементу, добавьте ее в качестве атрибута и свяжите входное значение appCopyToClipboard
с текстом, который вы хотите скопировать.
<button [appCopyToClipboard]="'Text to copy'">Copy to Clipboard</button>
В этом примере мы применили директиву appCopyToClipboard
к элементу кнопки. При нажатии пользователем на кнопку, текст "Text to copy" будет скопирован в буфер обмена.
Чтобы обеспечить распознавание и правильный импорт всех директив, вы можете попытаться импортировать их непосредственно в свой компонент или создать отдельный модуль Angular и импортировать все пользовательские директивы в этот модуль. Вот как вы можете это сделать:
Создайте новый модуль для ваших пользовательских директив (например, custom-directives.module.ts
):
import { NgModule } from '@angular/core';
// Import all your custom directives here
import { CustomValidationDirective } from './custom-validation.directive';
import { AutofocusDirective } from './autofocus.directive';
import { LazyLoadImagesDirective } from './lazy-load-images.directive';
import { DragAndDropDirective } from './drag-and-drop.directive';
import { EllipsisDirective } from './ellipsis.directive';
import { ClickOutsideDirective } from './click-outside.directive';
import { ConfirmDialogDirective } from './confirm-dialog.directive';
import { InfiniteScrollDirective } from './infinite-scroll.directive';
import { HighlightSearchDirective } from './highlight-search.directive';
import { ResponsiveDirective } from './responsive.directive';
import { InputMaskDirective } from './input-mask.directive';
import { TooltipDirective } from './tooltip.directive';
import { DisableRightClickDirective } from './disable-right-click.directive';
import { TimeAgoDirective } from './time-ago.directive';
import { CopyToClipboardDirective } from './copy-to-clipboard.directive';
@NgModule({
declarations: [
// Add all your custom directives here
CustomValidationDirective,
AutofocusDirective,
LazyLoadImagesDirective,
DragAndDropDirective,
EllipsisDirective,
ClickOutsideDirective,
ConfirmDialogDirective,
InfiniteScrollDirective,
HighlightSearchDirective,
ResponsiveDirective,
InputMaskDirective,
TooltipDirective,
DisableRightClickDirective,
TimeAgoDirective,
CopyToClipboardDirective,
],
exports: [
// Export all the directives so they can be used in other modules
CustomValidationDirective,
AutofocusDirective,
LazyLoadImagesDirective,
DragAndDropDirective,
EllipsisDirective,
ClickOutsideDirective,
ConfirmDialogDirective,
InfiniteScrollDirective,
HighlightSearchDirective,
ResponsiveDirective,
InputMaskDirective,
TooltipDirective,
DisableRightClickDirective,
TimeAgoDirective,
CopyToClipboardDirective,
],
})
export class CustomDirectivesModule {}
Импортируйте и используйте этот CustomDirectivesModule
в модуле, где вы хотите использовать ваши пользовательские директивы. Не забудьте добавить CustomDirectivesModule
в массив импортируемых модулей вашего модуля.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { CustomDirectivesModule } from './custom-directives.module';
@NgModule({
declarations: [
// Your components and other declarations
],
imports: [
BrowserModule,
CustomDirectivesModule, // Import your custom directives module here
],
bootstrap: [YourAppComponent],
})
export class YourAppModule {}
Заключение
Пользовательские директивы являются фундаментальной частью разработки на Angular и предлагают способ создания повторно используемых компонентов и добавления функциональности к элементам HTML. В этой статье мы рассмотрели концепцию кастомных директив и создали 15 примеров, чтобы продемонстрировать их универсальность. Используя и разрабатывая пользовательскиие директивы, вы можете сделать ваши приложения на Angular более модульными, легко поддерживаемыми и удобными для пользователей. Начните экспериментировать с пользовательскими директивами в своих проектах, чтобы раскрыть их полный потенциал.