0
# Navigation & Layout
1
2
Navigation and layout components including pagination, carousel, sortable lists, and progress indicators for content organization.
3
4
## Capabilities
5
6
### Pagination
7
8
Bootstrap pagination component with comprehensive navigation controls and event handling.
9
10
```typescript { .api }
11
/**
12
* Bootstrap pagination component
13
*/
14
@Component({
15
selector: 'pagination'
16
})
17
class PaginationComponent implements ControlValueAccessor, OnInit {
18
/** Align pagination to center */
19
@Input() align: boolean = false;
20
/** Show boundary links (first/last) */
21
@Input() boundaryLinks: boolean = false;
22
/** Show direction links (prev/next) */
23
@Input() directionLinks: boolean = true;
24
/** Disable pagination */
25
@Input() disabled: boolean = false;
26
/** First page link text */
27
@Input() firstText: string = 'First';
28
/** Last page link text */
29
@Input() lastText: string = 'Last';
30
/** Maximum number of page links to display */
31
@Input() maxSize: number = undefined;
32
/** Next page link text */
33
@Input() nextText: string = 'Next';
34
/** Previous page link text */
35
@Input() previousText: string = 'Previous';
36
/** Rotate pages when maxSize exceeded */
37
@Input() rotate: boolean = true;
38
/** Total number of items */
39
@Input() totalItems: number = 0;
40
/** Items per page */
41
@Input() itemsPerPage: number = 10;
42
/** Pagination size */
43
@Input() pageBtnClass: string = '';
44
/** Custom CSS class */
45
@Input() customPageTemplate: TemplateRef<PaginationLinkContext>;
46
/** Custom number template */
47
@Input() customNumberTemplate: TemplateRef<PaginationNumberLinkContext>;
48
49
/** Event emitted when number of pages changes */
50
@Output() numPages: EventEmitter<number> = new EventEmitter();
51
/** Event emitted when page changes */
52
@Output() pageChanged: EventEmitter<PageChangedEvent> = new EventEmitter();
53
54
/** Pages model */
55
pages: PagesModel[] = [];
56
/** Total pages */
57
totalPages: number = 0;
58
/** Current page */
59
page: number = 1;
60
61
/** Select page */
62
selectPage(page: number, event?: Event): void;
63
/** Get text for page */
64
getText(key: string): string;
65
/** Navigate to page */
66
noPrevious(): boolean;
67
/** Navigate to next */
68
noNext(): boolean;
69
}
70
71
/**
72
* Simple pager component with previous/next buttons
73
*/
74
@Component({
75
selector: 'pager'
76
})
77
class PagerComponent extends PaginationComponent {
78
/** Align pager buttons to edges */
79
@Input() pageBtnClass: string = '';
80
/** Previous button alignment */
81
@Input() previousClass: string = '';
82
/** Next button alignment */
83
@Input() nextClass: string = '';
84
85
/** Previous button text */
86
@Input() previousText: string = '« Previous';
87
/** Next button text */
88
@Input() nextText: string = 'Next »';
89
}
90
91
/**
92
* Event emitted when page changes
93
*/
94
interface PageChangedEvent {
95
/** Current page number */
96
page: number;
97
/** Items per page */
98
itemsPerPage: number;
99
}
100
101
/**
102
* Template context for pagination links
103
*/
104
interface PaginationLinkContext {
105
/** Page number */
106
$implicit: PagesModel;
107
/** Disabled state */
108
disabled: boolean;
109
}
110
111
/**
112
* Template context for pagination number links
113
*/
114
interface PaginationNumberLinkContext extends PaginationLinkContext {
115
/** Page content */
116
$implicit: PagesModel;
117
}
118
119
/**
120
* Page model for pagination
121
*/
122
interface PagesModel {
123
/** Page text */
124
text: string;
125
/** Page number */
126
number: number;
127
/** Active state */
128
active: boolean;
129
/** Disabled state */
130
disabled: boolean;
131
}
132
133
/**
134
* Global configuration for pagination
135
*/
136
@Injectable()
137
class PaginationConfig {
138
/** Default main class */
139
main: any = {
140
align: false,
141
boundaryLinks: false,
142
directionLinks: true,
143
firstText: 'First',
144
itemsPerPage: 10,
145
lastText: 'Last',
146
maxSize: undefined,
147
nextText: 'Next',
148
pageBtnClass: '',
149
previousText: 'Previous',
150
rotate: true,
151
totalItems: 0
152
};
153
/** Default pager class */
154
pager: any = {
155
align: true,
156
itemsPerPage: 15,
157
nextClass: '',
158
nextText: 'Next »',
159
pageBtnClass: 'btn-default',
160
previousClass: '',
161
previousText: '« Previous'
162
};
163
}
164
165
/**
166
* Angular module for pagination functionality
167
*/
168
@NgModule({
169
declarations: [PaginationComponent, PagerComponent],
170
exports: [PaginationComponent, PagerComponent]
171
})
172
class PaginationModule {}
173
```
174
175
**Usage Example:**
176
177
```typescript
178
import { PaginationModule } from 'ngx-bootstrap/pagination';
179
180
@Component({
181
template: `
182
<!-- Full pagination -->
183
<pagination
184
[(ngModel)]="currentPage"
185
[totalItems]="totalItems"
186
[itemsPerPage]="itemsPerPage"
187
[maxSize]="maxSize"
188
[boundaryLinks]="true"
189
[directionLinks]="true"
190
[rotate]="false"
191
(pageChanged)="onPageChanged($event)"
192
(numPages)="onNumPagesChanged($event)">
193
</pagination>
194
195
<!-- Simple pager -->
196
<pager
197
[(ngModel)]="currentPage"
198
[totalItems]="totalItems"
199
[itemsPerPage]="pageSize"
200
[previousText]="'‹ Previous'"
201
[nextText]="'Next ›'"
202
(pageChanged)="onPageChanged($event)">
203
</pager>
204
205
<!-- Display current data -->
206
<div>
207
Showing {{startItem}} to {{endItem}} of {{totalItems}} items
208
</div>
209
`,
210
imports: [PaginationModule]
211
})
212
export class MyComponent {
213
currentPage = 1;
214
totalItems = 100;
215
itemsPerPage = 10;
216
pageSize = 5;
217
maxSize = 5;
218
219
get startItem(): number {
220
return (this.currentPage - 1) * this.itemsPerPage + 1;
221
}
222
223
get endItem(): number {
224
return Math.min(this.currentPage * this.itemsPerPage, this.totalItems);
225
}
226
227
onPageChanged(event: PageChangedEvent) {
228
console.log('Page changed to:', event.page);
229
this.currentPage = event.page;
230
// Load data for current page
231
this.loadPageData(event.page);
232
}
233
234
onNumPagesChanged(numPages: number) {
235
console.log('Total pages:', numPages);
236
}
237
238
loadPageData(page: number) {
239
// Implement data loading logic
240
}
241
}
242
```
243
244
### Carousel
245
246
Image and content carousel with navigation, indicators, and auto-slide functionality.
247
248
```typescript { .api }
249
/**
250
* Bootstrap carousel component
251
*/
252
@Component({
253
selector: 'carousel'
254
})
255
class CarouselComponent implements OnDestroy, AfterViewInit {
256
/** Prevent looping to first slide */
257
@Input() noWrap: boolean = false;
258
/** Disable pause on hover */
259
@Input() noPause: boolean = false;
260
/** Show slide indicators */
261
@Input() showIndicators: boolean = true;
262
/** Auto-slide interval in milliseconds */
263
@Input() interval: number = 5000;
264
/** Pause on focus */
265
@Input() pauseOnFocus: boolean = false;
266
/** Wrap indicators by chunk */
267
@Input() indicatorsByChunk: boolean = false;
268
/** Items per slide */
269
@Input() itemsPerSlide: number = 1;
270
/** Single slide offset */
271
@Input() singleSlideOffset: boolean = false;
272
/** Start from index */
273
@Input() startFromIndex: number = 0;
274
275
/** Event emitted when active slide changes */
276
@Output() activeSlideChange: EventEmitter<number> = new EventEmitter();
277
/** Event emitted when slide range changes */
278
@Output() slideRangeChange: EventEmitter<number[]> = new EventEmitter();
279
280
/** Current active slide index */
281
activeSlide: number = 0;
282
/** Collection of slides */
283
slides: SlideComponent[] = [];
284
/** Slides currently displayed */
285
currentInterval: any;
286
/** Is playing */
287
isPlaying: boolean = false;
288
289
/** Add slide to carousel */
290
addSlide(slide: SlideComponent): void;
291
/** Remove slide from carousel */
292
removeSlide(slide: SlideComponent): void;
293
/** Navigate to next slide */
294
nextSlide(force?: boolean): void;
295
/** Navigate to previous slide */
296
previousSlide(force?: boolean): void;
297
/** Navigate to specific slide */
298
selectSlide(index: number): void;
299
/** Play carousel */
300
play(): void;
301
/** Pause carousel */
302
pause(): void;
303
/** Get current slides */
304
getCurrentSlides(): SlideComponent[];
305
/** Check if first slide */
306
isFirst(index: number): boolean;
307
/** Check if last slide */
308
isLast(index: number): boolean;
309
}
310
311
/**
312
* Individual slide component
313
*/
314
@Component({
315
selector: 'slide'
316
})
317
class SlideComponent implements OnInit, OnDestroy {
318
/** Slide active state */
319
@Input() active: boolean = false;
320
/** Slide index */
321
@Input() index: number;
322
323
/** Slide direction */
324
direction: string;
325
/** Slide class */
326
addClass: boolean = false;
327
}
328
329
/**
330
* Global configuration for carousel
331
*/
332
@Injectable()
333
class CarouselConfig {
334
/** Default slide interval */
335
interval: number = 5000;
336
/** Default no pause setting */
337
noPause: boolean = false;
338
/** Default no wrap setting */
339
noWrap: boolean = false;
340
/** Default indicators display */
341
showIndicators: boolean = true;
342
/** Default pause on focus */
343
pauseOnFocus: boolean = false;
344
/** Default indicators by chunk */
345
indicatorsByChunk: boolean = false;
346
/** Default items per slide */
347
itemsPerSlide: number = 1;
348
/** Default single slide offset */
349
singleSlideOffset: boolean = false;
350
/** Default starting index */
351
startFromIndex: number = 0;
352
}
353
354
/**
355
* Angular module for carousel functionality
356
*/
357
@NgModule({
358
declarations: [CarouselComponent, SlideComponent],
359
exports: [CarouselComponent, SlideComponent]
360
})
361
class CarouselModule {}
362
```
363
364
**Usage Example:**
365
366
```typescript
367
import { CarouselModule } from 'ngx-bootstrap/carousel';
368
369
@Component({
370
template: `
371
<carousel
372
[interval]="5000"
373
[noWrap]="false"
374
[showIndicators]="true"
375
[pauseOnFocus]="true"
376
(activeSlideChange)="onSlideChange($event)">
377
378
<slide *ngFor="let slide of slides; let index = index" [active]="slide.active">
379
<img [src]="slide.image" [alt]="slide.text" style="display: block; width: 100%;">
380
<div class="carousel-caption">
381
<h3>{{slide.text}}</h3>
382
<p>{{slide.description}}</p>
383
</div>
384
</slide>
385
</carousel>
386
387
<!-- Multi-item carousel -->
388
<carousel
389
[itemsPerSlide]="3"
390
[singleSlideOffset]="true"
391
[interval]="0"
392
[showIndicators]="false">
393
394
<slide *ngFor="let item of items">
395
<div class="item-content">
396
<h4>{{item.title}}</h4>
397
<p>{{item.content}}</p>
398
</div>
399
</slide>
400
</carousel>
401
`,
402
imports: [CarouselModule]
403
})
404
export class MyComponent {
405
slides = [
406
{
407
image: 'https://picsum.photos/800/400?random=1',
408
text: 'First Slide',
409
description: 'Description for first slide',
410
active: true
411
},
412
{
413
image: 'https://picsum.photos/800/400?random=2',
414
text: 'Second Slide',
415
description: 'Description for second slide',
416
active: false
417
},
418
{
419
image: 'https://picsum.photos/800/400?random=3',
420
text: 'Third Slide',
421
description: 'Description for third slide',
422
active: false
423
}
424
];
425
426
items = [
427
{ title: 'Item 1', content: 'Content 1' },
428
{ title: 'Item 2', content: 'Content 2' },
429
{ title: 'Item 3', content: 'Content 3' },
430
{ title: 'Item 4', content: 'Content 4' },
431
{ title: 'Item 5', content: 'Content 5' },
432
{ title: 'Item 6', content: 'Content 6' }
433
];
434
435
onSlideChange(slideIndex: number) {
436
console.log('Active slide changed to:', slideIndex);
437
}
438
}
439
```
440
441
### Progress Bar
442
443
Bootstrap progress bars with multiple bars, labels, and animation support.
444
445
```typescript { .api }
446
/**
447
* Bootstrap progress bar component
448
*/
449
@Component({
450
selector: 'progressbar'
451
})
452
class ProgressbarComponent implements OnInit {
453
/** Maximum progress value */
454
@Input() max: number = 100;
455
/** Progress bar type */
456
@Input() type: string;
457
/** Progress value */
458
@Input() value: number = 0;
459
/** Animated progress bar */
460
@Input() animate: boolean = false;
461
/** Striped progress bar */
462
@Input() striped: boolean = false;
463
464
/** Current percentage */
465
percent: number = 0;
466
/** Progress class */
467
addClass: boolean = true;
468
}
469
470
/**
471
* Individual progress bar segment
472
*/
473
@Component({
474
selector: 'bar'
475
})
476
class BarComponent implements OnInit {
477
/** Bar type (success, info, warning, danger) */
478
@Input() type: string;
479
/** Bar value */
480
@Input() value: number = 0;
481
482
/** Bar percentage */
483
percent: number = 0;
484
}
485
486
/**
487
* Progress bar type interface
488
*/
489
interface ProgressbarType {
490
[key: string]: {
491
/** CSS class for progress bar type */
492
cssClass: string;
493
/** Text color class */
494
textClass?: string;
495
};
496
}
497
498
/**
499
* Global configuration for progress bars
500
*/
501
@Injectable()
502
class ProgressbarConfig {
503
/** Default animate setting */
504
animate: boolean = false;
505
/** Default maximum value */
506
max: number = 100;
507
}
508
509
/**
510
* Angular module for progress bar functionality
511
*/
512
@NgModule({
513
declarations: [ProgressbarComponent, BarComponent],
514
exports: [ProgressbarComponent, BarComponent]
515
})
516
class ProgressbarModule {}
517
```
518
519
**Usage Example:**
520
521
```typescript
522
import { ProgressbarModule } from 'ngx-bootstrap/progressbar';
523
524
@Component({
525
template: `
526
<!-- Simple progress bar -->
527
<progressbar
528
[value]="progress"
529
[max]="100"
530
[type]="'success'"
531
[animate]="true"
532
[striped]="true">
533
{{progress}}%
534
</progressbar>
535
536
<!-- Multiple bars -->
537
<progressbar [max]="max">
538
<bar [value]="stacked[0].value" [type]="stacked[0].type">{{stacked[0].label}}</bar>
539
<bar [value]="stacked[1].value" [type]="stacked[1].type">{{stacked[1].label}}</bar>
540
<bar [value]="stacked[2].value" [type]="stacked[2].type">{{stacked[2].label}}</bar>
541
</progressbar>
542
543
<!-- Dynamic progress bars -->
544
<div *ngFor="let bar of dynamicBars">
545
<progressbar
546
[value]="bar.value"
547
[type]="bar.type"
548
[striped]="bar.striped"
549
[animate]="bar.animate">
550
<b>{{bar.value}}%</b>
551
</progressbar>
552
</div>
553
`,
554
imports: [ProgressbarModule]
555
})
556
export class MyComponent {
557
progress = 75;
558
max = 200;
559
560
stacked = [
561
{ value: 15, type: 'info', label: 'Type 1' },
562
{ value: 30, type: 'warning', label: 'Type 2' },
563
{ value: 20, type: 'danger', label: 'Type 3' }
564
];
565
566
dynamicBars = [
567
{ value: 25, type: 'success', striped: false, animate: false },
568
{ value: 50, type: 'info', striped: true, animate: true },
569
{ value: 75, type: 'warning', striped: true, animate: false },
570
{ value: 100, type: 'danger', striped: false, animate: true }
571
];
572
573
// Update progress
574
updateProgress() {
575
this.progress = Math.floor(Math.random() * 100) + 1;
576
}
577
}
578
```
579
580
### Sortable
581
582
Drag-and-drop sortable lists with customizable options and event handling.
583
584
```typescript { .api }
585
/**
586
* Sortable component for drag-and-drop lists
587
*/
588
@Component({
589
selector: 'bs-sortable'
590
})
591
class SortableComponent implements OnInit {
592
/** Sortable items */
593
@Input() items: SortableItem[] = [];
594
/** Field name for display */
595
@Input() fieldName: string = 'value';
596
/** Placeholder text when dragging */
597
@Input() placeholderItem: string = '';
598
/** Placeholder CSS class */
599
@Input() placeholderClass: string = '';
600
/** Item CSS class */
601
@Input() itemClass: string = '';
602
/** Active item CSS class */
603
@Input() itemActiveClass: string = '';
604
/** Item template */
605
@Input() itemTemplate: TemplateRef<any>;
606
/** Wrap class */
607
@Input() wrapperClass: string = '';
608
609
/** Event emitted when items change */
610
@Output() onChange: EventEmitter<any[]> = new EventEmitter();
611
612
/** Get item text */
613
getItemText(item: SortableItem): string;
614
/** Check if item is active */
615
isItemActive(item: SortableItem): boolean;
616
/** Move item up */
617
moveUp(item: SortableItem): void;
618
/** Move item down */
619
moveDown(item: SortableItem): void;
620
/** Remove item */
621
removeItem(item: SortableItem): void;
622
}
623
624
/**
625
* Sortable item interface
626
*/
627
interface SortableItem {
628
/** Item ID */
629
id: number;
630
/** Item value/text */
631
value: string;
632
/** Active state */
633
isActive?: boolean;
634
/** Disabled state */
635
isDisabled?: boolean;
636
}
637
638
/**
639
* Draggable item class
640
*/
641
class DraggableItem {
642
constructor(
643
/** Item data */
644
public item: SortableItem,
645
/** Item index */
646
public index: number
647
) {}
648
649
/** Get item value */
650
getValue(): string;
651
/** Get item index */
652
getIndex(): number;
653
}
654
655
/**
656
* Service for handling drag operations
657
*/
658
@Injectable()
659
class DraggableItemService {
660
/** Draggable item */
661
draggableItem: DraggableItem;
662
663
/** Get draggable item */
664
getDraggableItem(): DraggableItem;
665
/** Set draggable item */
666
setDraggableItem(item: DraggableItem): void;
667
/** Clear draggable item */
668
clearDraggableItem(): void;
669
}
670
671
/**
672
* Angular module for sortable functionality
673
*/
674
@NgModule({
675
declarations: [SortableComponent],
676
exports: [SortableComponent],
677
providers: [DraggableItemService]
678
})
679
class SortableModule {}
680
```
681
682
**Usage Example:**
683
684
```typescript
685
import { SortableModule } from 'ngx-bootstrap/sortable';
686
687
@Component({
688
template: `
689
<bs-sortable
690
[items]="sortableItems"
691
[fieldName]="'text'"
692
[itemClass]="'list-group-item'"
693
[itemActiveClass]="'list-group-item-success'"
694
[placeholderItem]="'Drag here'"
695
[placeholderClass]="'list-group-item list-group-item-light'"
696
[wrapperClass]="'list-group'"
697
(onChange)="onSortableChange($event)">
698
</bs-sortable>
699
700
<!-- Custom template -->
701
<bs-sortable
702
[items]="customItems"
703
[itemTemplate]="customTemplate"
704
(onChange)="onCustomChange($event)">
705
</bs-sortable>
706
707
<ng-template #customTemplate let-item="item" let-index="index">
708
<div class="card mb-2">
709
<div class="card-body">
710
<h6 class="card-title">{{item.title}}</h6>
711
<p class="card-text">{{item.description}}</p>
712
<small class="text-muted">Item {{index + 1}}</small>
713
</div>
714
</div>
715
</ng-template>
716
`,
717
imports: [SortableModule]
718
})
719
export class MyComponent {
720
sortableItems = [
721
{ id: 1, text: 'First Item', isActive: false },
722
{ id: 2, text: 'Second Item', isActive: false },
723
{ id: 3, text: 'Third Item', isActive: true },
724
{ id: 4, text: 'Fourth Item', isActive: false }
725
];
726
727
customItems = [
728
{
729
id: 1,
730
title: 'Task 1',
731
description: 'Complete project documentation',
732
value: 'Task 1'
733
},
734
{
735
id: 2,
736
title: 'Task 2',
737
description: 'Review code changes',
738
value: 'Task 2'
739
},
740
{
741
id: 3,
742
title: 'Task 3',
743
description: 'Deploy to production',
744
value: 'Task 3'
745
}
746
];
747
748
onSortableChange(items: any[]) {
749
console.log('Sortable items changed:', items);
750
this.sortableItems = items;
751
}
752
753
onCustomChange(items: any[]) {
754
console.log('Custom items changed:', items);
755
this.customItems = items;
756
}
757
}
758
```