Angular गाइड
@reelkit/angular से स्लाइडर बनाना सीखें।
rk-reel कंपोनेंट
rk-reel कंपोनेंट core स्लाइडर कंट्रोलर को लपेटता है। Standalone, ChangeDetectionStrategy.OnPush के साथ।
import { Component } from '@angular/core';
import { ReelComponent, ReelIndicatorComponent, RkReelItemDirective } from '@reelkit/angular';
@Component({
selector: 'app-root',
standalone: true,
imports: [ReelComponent, ReelIndicatorComponent, RkReelItemDirective],
template: `
<rk-reel
[count]="items.length"
style="width: 100%; height: 100dvh"
direction="vertical"
[enableWheel]="true"
(afterChange)="onAfterChange($event)"
>
<ng-template rkReelItem let-i let-size="size">
<div [style.width.px]="size[0]" [style.height.px]="size[1]"
[style.background]="items[i].color"
style="display:flex;flex-direction:column;align-items:center;justify-content:center;color:#fff">
<div style="font-size:1.5rem;font-weight:bold">{{ items[i].title }}</div>
<div style="font-size:0.875rem;opacity:0.8">{{ items[i].subtitle }}</div>
</div>
</ng-template>
<div style="position:absolute;right:12px;top:50%;transform:translateY(-50%);z-index:10">
<rk-reel-indicator direction="vertical" />
</div>
</rk-reel>
`,
})
export class AppComponent {
items = [
{ title: 'Virtualized', subtitle: 'Only 3 slides in DOM', color: '#6366f1' },
{ title: 'Touch First', subtitle: 'Native swipe gestures', color: '#8b5cf6' },
{ title: 'Zero Deps', subtitle: 'Tiny bundle size', color: '#7c3aed' },
{ title: 'Keyboard Nav', subtitle: 'Full a11y support', color: '#ec4899' },
{ title: 'SSR Ready', subtitle: 'Works everywhere', color: '#14b8a6' },
{ title: '60fps', subtitle: 'Smooth animations', color: '#f59e0b' },
];
onAfterChange(event: { index: number; indexInRange: number }) {
console.log('Current index:', event.index);
}
}अपने-आप साइज़
size input वैकल्पिक है। इसे छोड़ने पर rk-reel ResizeObserver से अपना कंटेनर खुद नापता है और CSS से तय लेआउट के हिसाब से ढल जाता है। कंटेनर का साइज़ उसके parent से तय होना चाहिए (जैसे flex, grid या तय CSS आकार)।
<!-- Explicit size (fixed) -->
<rk-reel [count]="items.length" [size]="[400, 600]">
<ng-template rkReelItem let-i let-size="size"> ... </ng-template>
</rk-reel>
<!-- Auto-size (responsive — sized by CSS) -->
<rk-reel [count]="items.length" style="width: 100%; height: 100dvh">
<ng-template rkReelItem let-i let-size="size"> ... </ng-template>
</rk-reel>rkReelItem टेम्पलेट पैटर्न
React के render prop की जगह Angular ng-template पर structural directive rkReelItem इस्तेमाल करता है। इससे वर्चुअलाइज़ेशन संभव होता है — सिर्फ़ दिखने वाली स्लाइड बनती हैं। Template context तीन variables देता है:
<ng-template rkReelItem let-i let-indexInRange="indexInRange" let-size="size">
<!--
$implicit (let-i) : number — absolute slide index (0 to count-1)
indexInRange : number — position in visible window (0, 1, or 2)
size : [number, number] — [width, height] of the container
-->
<app-slide [data]="items[i]"
[style.width.px]="size[0]"
[style.height.px]="size[1]" />
</ng-template>नेविगेशन
नेविगेशन के बिल्ट-इन तरीके:
- टच/स्वाइप: momentum और snap के साथ खींचकर आगे-पीछे जाएँ
- कीबोर्ड: तीर वाली कुंजियाँ और Escape
- माउस व्हील:
[enableWheel]="true"से चालू करें - प्रोग्राम से:
next(),prev(),goTo()पाने के लिए(apiReady)output इस्तेमाल करें
import { Component } from '@angular/core';
import { ReelComponent, RkReelItemDirective, type ReelApi } from '@reelkit/angular';
@Component({
selector: 'app-root',
standalone: true,
imports: [ReelComponent, RkReelItemDirective],
template: `
<rk-reel
[count]="10"
[size]="[400, 600]"
(apiReady)="api = $event"
>
<ng-template rkReelItem let-i let-size="size">
<app-slide [index]="i" [size]="size" />
</ng-template>
</rk-reel>
<button (click)="api?.prev()">Prev</button>
<button (click)="api?.next()">Next</button>
<button (click)="api?.goTo(5)">Go to 5</button>
`,
})
export class AppComponent {
api: ReelApi | undefined;
}URL स्टेट
createOverlayUrlState किसी overlay के लिए URL-स्टेट कंट्रोलर बनाकर पूरा लौटाता है, फिर आप उसे किसी *UrlOverlay कंपोनेंट को उसके [controller] input के रूप में देते हैं। इसे injection context में कॉल करें — field initialiser में; यह तुरंत जुड़ता है और DestroyRef से छूटता है। खुले होने की स्टेट URL के पास है, इसलिए जुड़ा हुआ overlay खुद खुलता है और आम तौर पर लि ंक ही उसे खोलता है। न मौजूद parameter का पहला write history में एक entry जोड़ता है और उसके बाद हर write उसे बदल देता है, इसलिए पेज बदलना back बटन को कभी दबाता नहीं। value/position पढ़ने और प्रोग्राम से चलाने के लिए कंट्रोलर रखें: set(position) खोलता है, set(null) बंद करता है, और set वही निचले स्तर का write है जो overlay स्लाइड बदलने पर अंदर से करता है।
import { Component, signal } from '@angular/core';
import { RouterLink } from '@angular/router';
import { RkLightboxUrlOverlayComponent } from '@reelkit/angular-lightbox';
import { createOverlayUrlState, urlIndexKey } from '@reelkit/angular';
@Component({
imports: [RkLightboxUrlOverlayComponent, RouterLink],
template: `
@for (image of images(); track image.src; let i = $index) {
<a [routerLink]="[]" [queryParams]="{ photo: i }">
<img [src]="image.src" alt="" />
</a>
}
<rk-lightbox-url-overlay [controller]="photo" [items]="images()" />
`,
})
export class GalleryComponent {
protected readonly images = signal(photos);
// Attaches now, releases on destroy.
protected readonly photo = createOverlayUrlState({
param: 'photo',
...urlIndexKey(() => this.images().length),
});
}Routing वाला ऐप — Router पर आधारित adapter पास करें, नहीं तो Router की अपनी location पुरानी पड़ जाती है और उसका अगला नेविगेशन parameter गिरा देता है:
import { createRouterUrlAdapter } from '@reelkit/angular/ng-router-url-adapter';
protected readonly photo = createOverlayUrlState({
param: 'photo',
adapter: createRouterUrlAdapter(),
...urlIndexKey(() => this.images().length),
});विकल्पों का object param, codec और locator (तीनों ज़रूरी) लेता है, साथ में वैकल्पिक adapter। codec और locator एक ही Id साझा करने वाली मेल खाती जोड़ी हैं, इसलिए साधारण ?photo=3 गैलरी ...urlIndexKey(() => images().length) spread करती है, जो दोनों हिस्से एक साथ लौटाता है। urlIndexKey index को getter की लौटाई मौजूदा गिनती तक सीमित रखता है, इसलिए पुराना ?photo=99 ठुकराया जाता है और कभी नाम न ली गई स्लाइड खोलने के बजाय URL से अपने-आप हट जाता है। पेज वाली फ़ीड या पहचान से key होने वाली गैलरी इसकी जगह अपनी मेल खाती codec + locator जोड़ी देती है। विकल्पों की पूरी तालिका Angular API रेफ़रेंस में है।
ReelIndicator
एक वैकल्पिक कंपोनेंट, जो Instagram जैसे प्रोग्रेस इंडिकेटर दिखाता है कि आप स्लाइडर में अभी किस जगह पर हैं। rk-reel के अंदर रखने पर यह RK_REEL_CONTEXT injection token के ज़रिए parent की count और active values से अपने-आप जुड़ जाता है — हाथ से जोड़ने की ज़रूरत नहीं।
<!-- Auto-connect: count and active are inherited from parent rk-reel -->
<rk-reel [count]="10" [size]="[400, 600]">
<ng-template rkReelItem let-i let-size="size"> ... </ng-template>
<rk-reel-indicator direction="vertical" />
</rk-reel>
<!-- Manual usage: pass count and active explicitly (e.g. outside a rk-reel) -->
<rk-reel-indicator [count]="10" [active]="currentIndex" />apiReady output — सिग्नल पर आधारित पैटर्न
(apiReady) output कंपोनेंट के mount होने और नापे जाने के बाद एक बार चलता है। यह एक ReelApi object देता है, जिसे आप रख सकते हैं और imperative नेविगेशन के लिए इस्तेमाल कर सकते हैं। इस reference के लिए Angular signals इस्तेमाल करना OnPush change detection के साथ साफ़ तरीके से काम करता है।
import { Component, signal } from '@angular/core';
import { ReelComponent, RkReelItemDirective, type ReelApi } from '@reelkit/angular';
@Component({
selector: 'app-root',
standalone: true,
imports: [ReelComponent, RkReelItemDirective],
template: `
<rk-reel
[count]="items.length"
style="width: 100%; height: 100dvh"
direction="vertical"
[enableWheel]="true"
(apiReady)="reelApi.set($event)"
(afterChange)="currentIndex.set($event.index)"
>
<ng-template rkReelItem let-i let-size="size">
<div [style.width.px]="size[0]" [style.height.px]="size[1]">
{{ items[i].title }}
</div>
</ng-template>
</rk-reel>
<div style="position:absolute;bottom:16px;left:50%;transform:translateX(-50%)">
<button (click)="reelApi()?.prev()"
[disabled]="currentIndex() === 0">Prev</button>
<button (click)="reelApi()?.next()"
[disabled]="currentIndex() === items.length - 1">Next</button>
</div>
`,
})
export class AppComponent {
readonly items = [
{ title: 'Slide 1', color: '#6366f1' },
{ title: 'Slide 2', color: '#8b5cf6' },
{ title: 'Slide 3', color: '#ec4899' },
];
readonly reelApi = signal<ReelApi | undefined>(undefined);
readonly currentIndex = signal(0);
}मुख्य बातें
- Standalone कंपोनेंट
ReelComponent,RkReelItemDirectiveऔर ज़रूरत हो तोReelIndicatorComponentको सीधे अपने कंपोनेंट केimportsarray में import करें - ng-template + rkReelItem
React के
itemBuilderprop का Angular वाला रूप — वर्चुअलाइज़ेशन संभव बनाता है - apiReady
output, जो imperative नेविगेशन API के साथ एक बार चलता है — ViewChild query की ज़रूरत नहीं
- afterChange
{ index, indexInRange }emit करता है — UI अपडेट के लिए मौजूदा index पर नज़र रखें - डिफ़ॉल्ट रूप से OnPush
सबसे अच्छे परफ़ॉर्मेंस के लिए सारे कंपोनेंट
ChangeDetectionStrategy.OnPushऔर Angular signals इस्तेमाल करते हैं
परफ़ॉर्मेंस टिप्स
- स्लाइड templates को हल्का रखें
rkReelItemtemplate हर दिखने वाली स्लाइड के लिए चलता है (आम तौर पर एक बार में 3)। इसके अंदर भारी गणना या बहुत गहरी nested संरचना से बचें। - किनारे के पास डेटा लोड करें
(afterChange)से पहचानें कि यूज़र आख़िर के पास पहुँच रहा है, और स्लाइड ख़त्म होने से पहले अगला बैच fetch करें — इससे अनंत स्क्रॉल वाली फ़ीड बनती है। - imperative स्टेट के लिए signals इस्तेमाल करें
पूरे कंपोनेंट को दोबारा रेंडर किए बिना बारीक reactivity पाने के लिए
ReelApireference और मौजूदा index को Angular signals में रखें। - स्क्रॉल होने वाले पेज में व्हील बंद करें
जब स्लाइडर स्क्रॉल होने वाले लेआउट के अंदर हो, तो पेज का स्क्रॉल पकड़ने से बचने के लिए
[enableWheel]="false"सेट करें।
अगले कदम
- Angular API रेफ़रेंस - सभी उपलब्ध inputs, outputs और मेथड
- Reel Player - TikTok/Reels जैसा वीडियो प्लेयर
- Lightbox - इमेज और वीडियो गैलरी
- Stories Player - Instagram जैसा stories व्यूअर