or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

form-controls.mdindex.mdinteractive-components.mdnavigation-layout.mdoverlays-popovers.mdutilities-infrastructure.md

navigation-layout.mddocs/

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

```