Advanced
Nima bu?
Directive Composition API komponent yoki directive'ga boshqa directive'larni hostDirectives orqali qo'shish imkonini beradi. Kod takrorlanishini kamaytiradi — masalan, FocusTrapDirective va AriaLabelDirective ni bir nechta komponentga alohida import qilmasdan biriktirish.
Kod misoli
import { Directive, HostBinding, HostListener, Input } from '@angular/core';
@Directive({
selector: '[appFocusTrap]',
standalone: true,
})
export class FocusTrapDirective {
@HostListener('keydown.tab', ['$event'])
onTab(event: KeyboardEvent): void {
event.preventDefault();
console.log('Tab ushlandi — fokus ichida qoladi');
}
}
@Directive({
selector: '[appAriaLabel]',
standalone: true,
})
export class AriaLabelDirective {
@Input('appAriaLabel') label = '';
@HostBinding('attr.aria-label') get ariaLabel(): string {
return this.label;
}
}
@Component({
selector: 'app-modal',
standalone: true,
hostDirectives: [
FocusTrapDirective,
{ directive: AriaLabelDirective, inputs: ['appAriaLabel: modalTitle'] },
],
template: `
<div class="modal">
<h2>{{ modalTitle }}</h2>
<ng-content />
</div>
`,
})
export class ModalComponent {
modalTitle = 'Tasdiqlash';
}
Muhim cheklov: host directive'ning @Input/@Outputlari default holda tashqariga chiqmaydi — faqat inputs/outputs array'ida aniq ro'yxatga olinganlari parent uchun ko'rinadi (yuqoridagi misolda AriaLabelDirective ning appAriaLabel inputi modalTitle nomiga alias qilib ochilgan, lekin ro'yxatga olinmagan boshqa property'lari butunlay yopiq qoladi). Bu inkapsulyatsiya uchun ataylab shunday — NgModule orqali qo'shilgan directive'dan farqli o'laroq, hostDirective host component template'ida shartli (*ngIf) qo'llanilmaydi, u doim komponent instance'i bilan birga yaratiladi.
Imtihonda
hostDirectivesvs template'da directive qo'llash?- Input alias qanday uzatiladi?
- hostDirectives output'larini parent qanday eshitadi?
- hostDirective'ning e'lon qilinmagan input/output'lariga tashqaridan kirish mumkinmi?
Yodlash uchun
hostDirectives = directive kompozitsiyasi; v15+; standalone bilan ishlaydi; faqat ro'yxatga olingan input/output tashqariga chiqadi.
Nima bu?
exportAs directive yoki komponentni template reference variable orqali klass instance sifatida eksport qiladi. #ref="ngForm", #dir="appTooltip" kabi — template ichidan directive metodlariga va property'lariga kirish mumkin.
Kod misoli
import { Directive, Input, HostListener } from '@angular/core';
@Directive({
selector: '[appTooltip]',
standalone: true,
exportAs: 'appTooltip',
})
export class TooltipDirective {
@Input('appTooltip') text = '';
visible = false;
@HostListener('mouseenter')
show(): void {
this.visible = true;
console.log('Tooltip:', this.text);
}
@HostListener('mouseleave')
hide(): void {
this.visible = false;
}
toggle(): void {
this.visible = !this.visible;
}
}
<button
appTooltip="Yordam matni"
#tip="appTooltip"
(click)="tip.toggle()"
>
Hover yoki bosing
</button>
<p>Holat: {{ tip.visible ? 'ko\'rinadi' : 'yashirin' }}</p>
Imtihonda
exportAsbo'lmasa template ref nima qaytaradi?- Bir elementda
#a="ngModel"va#b="appTooltip"mumkinmi? - Component'da
exportAsqanday ishlatiladi?
Yodlash uchun
exportAs = template ref nomi; #ref="exportAsValue".
Nima bu?
Angular CDK (Component Dev Kit) @angular/cdk production-ready directive va servislarni taqdim etadi: Drag & Drop (cdkDrag, cdkDropList), Overlay (modal, tooltip portali), Scrolling (virtual scroll). Material UI'siz ham ishlatish mumkin.
Kod misoli
import { Component } from '@angular/core';
import {
CdkDrag,
CdkDragDrop,
CdkDropList,
moveItemInArray,
} from '@angular/cdk/drag-drop';
import { OverlayModule } from '@angular/cdk/overlay';
interface Task {
id: number;
title: string;
}
@Component({
selector: 'app-kanban',
standalone: true,
imports: [CdkDropList, CdkDrag, OverlayModule],
template: `
<div
cdkDropList
class="column"
[cdkDropListData]="tasks"
(cdkDropListDropped)="drop($event)"
>
@for (task of tasks; track task.id) {
<div cdkDrag class="card">
{{ task.title }}
<div *cdkDragPlaceholder class="placeholder"></div>
</div>
}
</div>
`,
styles: [`
.column { min-height: 200px; padding: 1rem; background: #f3f4f6; }
.card { padding: 0.5rem; margin: 0.25rem 0; background: #fff; cursor: move; }
.placeholder { height: 40px; background: #dbeafe; border: 2px dashed #3b82f6; }
`],
})
export class KanbanComponent {
tasks: Task[] = [
{ id: 1, title: 'Dizayn' },
{ id: 2, title: 'Backend API' },
{ id: 3, title: 'Test yozish' },
];
drop(event: CdkDragDrop<Task[]>): void {
moveItemInArray(this.tasks, event.previousIndex, event.currentIndex);
}
}
CDK vs Material: Material — tayyor stildagi component'lar (mat-button, mat-select); CDK — o'sha component'larning ichidagi stilsiz (unstyled) mantiq — a11y, focus trap, positioning, drag mexanikasi. Shu sabab custom design system quruvchi jamoalar Material'ni butunlay o'tkazib yuborib, faqat CDK'dan foydalanadi. CdkVirtualScrollViewport bilan ishlaganda itemSize noto'g'ri berilsa scroll pozitsiyasi va DOM recycle noto'g'ri hisoblanadi — bu ko'p uchraydigan production xato. Overlay esa ViewContainerRef context'idan tashqarida, document.bodyga yaqin alohida DOM daraxtida render qiladi (portal pattern) — shuning uchun z-index va CSS encapsulation muammolari kamroq.
Imtihonda
- CDK vs Angular Material farqi?
cdkDragaccessibility qo'llab-quvvatlaydimi?- Overlay service qanday ishlatiladi?
CdkVirtualScrollViewportdaitemSizenoto'g'ri bo'lsa nima buziladi?
Yodlash uchun
CDK = headless UI primitivlar; drag-drop, overlay (portal pattern), virtual scroll (itemSize muhim).
