or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

accordion.mdalert.mdcarousel.mddatepicker.mdfeedback.mdforms.mdindex.mdlayout.mdmodal.mdnavigation.md

layout.mddocs/

0

# Layout Components

1

2

Layout and structural components including collapse, offcanvas, pagination, dropdown, progressbar, and scrollspy for organizing content and navigation.

3

4

## Core Imports

5

6

```typescript

7

import {

8

NgbCollapseModule,

9

NgbOffcanvasModule,

10

NgbPaginationModule,

11

NgbDropdownModule,

12

NgbProgressbarModule,

13

NgbScrollSpyModule

14

} from '@ng-bootstrap/ng-bootstrap';

15

```

16

17

## Capabilities

18

19

### NgbCollapse

20

21

Directive for collapsible content areas.

22

23

```typescript { .api }

24

@Directive({

25

selector: '[ngbCollapse]',

26

exportAs: 'ngbCollapse'

27

})

28

class NgbCollapse {

29

/** Controls collapsed state */

30

@Input() ngbCollapse: boolean;

31

32

/** Enable/disable animations */

33

@Input() animation: boolean;

34

35

/** Event emitted when collapse state changes */

36

@Output() ngbCollapseChange: EventEmitter<boolean>;

37

38

/** Toggle collapsed state */

39

toggle(): void;

40

}

41

```

42

43

### NgbOffcanvas

44

45

Service for opening and managing offcanvas panels.

46

47

```typescript { .api }

48

@Injectable({ providedIn: 'root' })

49

class NgbOffcanvas {

50

/** Open an offcanvas panel */

51

open(content: any, options?: NgbOffcanvasOptions): NgbOffcanvasRef;

52

53

/** Dismiss all open offcanvas panels */

54

dismissAll(reason?: any): void;

55

56

/** Check if there are any open offcanvas panels */

57

hasOpenOffcanvas(): boolean;

58

}

59

```

60

61

### NgbOffcanvasRef

62

63

Reference to an opened offcanvas instance.

64

65

```typescript { .api }

66

class NgbOffcanvasRef {

67

/** Instance of the component if offcanvas contains a component */

68

componentInstance?: any;

69

70

/** Promise that resolves when offcanvas is closed or dismissed */

71

result: Promise<any>;

72

73

/** Close the offcanvas with a result */

74

close(result?: any): void;

75

76

/** Dismiss the offcanvas with a reason */

77

dismiss(reason?: any): void;

78

}

79

```

80

81

### NgbActiveOffcanvas

82

83

Reference to the currently active offcanvas (used within offcanvas content).

84

85

```typescript { .api }

86

@Injectable()

87

class NgbActiveOffcanvas {

88

/** Close the offcanvas with a result */

89

close(result?: any): void;

90

91

/** Dismiss the offcanvas with a reason */

92

dismiss(reason?: any): void;

93

}

94

```

95

96

### Pagination Components

97

98

Components for navigating through pages of content with customizable templates.

99

100

#### NgbPagination

101

102

Main pagination component that displays page numbers and navigation links.

103

104

```typescript { .api }

105

@Component({

106

selector: 'ngb-pagination',

107

exportAs: 'ngbPagination'

108

})

109

class NgbPagination {

110

/** If true, pagination links will be disabled */

111

@Input() disabled: boolean;

112

113

/** If true, the "First" and "Last" page links are shown */

114

@Input() boundaryLinks: boolean;

115

116

/** If true, the "Next" and "Previous" page links are shown */

117

@Input() directionLinks: boolean;

118

119

/** If true, ellipsis symbols and first/last page numbers shown when maxSize > pages */

120

@Input() ellipses: boolean;

121

122

/** Whether to rotate pages when maxSize > number of pages */

123

@Input() rotate: boolean;

124

125

/** The number of items in your paginated collection (required) */

126

@Input({ required: true }) collectionSize: number;

127

128

/** The maximum number of pages to display */

129

@Input() maxSize: number;

130

131

/** The current page (starts with 1) */

132

@Input() page: number;

133

134

/** The number of items per page */

135

@Input() pageSize: number;

136

137

/** The pagination display size: 'sm', 'lg', or custom string */

138

@Input() size: 'sm' | 'lg' | string | null;

139

140

/** Event fired when page is changed */

141

@Output() pageChange: EventEmitter<number>;

142

143

/** Total number of pages */

144

pageCount: number;

145

146

/** Array of page numbers to display */

147

pages: number[];

148

149

/** Navigate to specific page */

150

selectPage(pageNumber: number): void;

151

152

/** Check if there's a previous page */

153

hasPrevious(): boolean;

154

155

/** Check if there's a next page */

156

hasNext(): boolean;

157

158

/** Check if next button should be disabled */

159

nextDisabled(): boolean;

160

161

/** Check if previous button should be disabled */

162

previousDisabled(): boolean;

163

}

164

```

165

166

#### Pagination Template Directives

167

168

Template directives for customizing pagination appearance.

169

170

```typescript { .api }

171

/** Template directive for ellipsis (...) */

172

@Directive({ selector: 'ng-template[ngbPaginationEllipsis]' })

173

class NgbPaginationEllipsis {

174

templateRef: TemplateRef<NgbPaginationLinkContext>;

175

}

176

177

/** Template directive for first page link */

178

@Directive({ selector: 'ng-template[ngbPaginationFirst]' })

179

class NgbPaginationFirst {

180

templateRef: TemplateRef<NgbPaginationLinkContext>;

181

}

182

183

/** Template directive for last page link */

184

@Directive({ selector: 'ng-template[ngbPaginationLast]' })

185

class NgbPaginationLast {

186

templateRef: TemplateRef<NgbPaginationLinkContext>;

187

}

188

189

/** Template directive for next page link */

190

@Directive({ selector: 'ng-template[ngbPaginationNext]' })

191

class NgbPaginationNext {

192

templateRef: TemplateRef<NgbPaginationLinkContext>;

193

}

194

195

/** Template directive for page number links */

196

@Directive({ selector: 'ng-template[ngbPaginationNumber]' })

197

class NgbPaginationNumber {

198

templateRef: TemplateRef<NgbPaginationNumberContext>;

199

}

200

201

/** Template directive for previous page link */

202

@Directive({ selector: 'ng-template[ngbPaginationPrevious]' })

203

class NgbPaginationPrevious {

204

templateRef: TemplateRef<NgbPaginationLinkContext>;

205

}

206

207

/** Template directive for all pages content */

208

@Directive({ selector: 'ng-template[ngbPaginationPages]' })

209

class NgbPaginationPages {

210

templateRef: TemplateRef<NgbPaginationPagesContext>;

211

}

212

```

213

214

#### Pagination Context Interfaces

215

216

```typescript { .api }

217

interface NgbPaginationLinkContext {

218

/** Page number displayed by the current link */

219

currentPage: number;

220

/** If true, the current link is disabled */

221

disabled: boolean;

222

}

223

224

interface NgbPaginationNumberContext extends NgbPaginationLinkContext {

225

/** The page number, displayed by the current page link */

226

$implicit: number;

227

}

228

229

interface NgbPaginationPagesContext {

230

/** The currently selected page number */

231

$implicit: number;

232

/** If true, pagination is disabled */

233

disabled: boolean;

234

/** Pages numbers that should be rendered starting with 1 */

235

pages: number[];

236

}

237

```

238

239

#### NgbPaginationConfig

240

241

Configuration service for pagination defaults.

242

243

```typescript { .api }

244

@Injectable({ providedIn: 'root' })

245

class NgbPaginationConfig {

246

disabled: boolean;

247

boundaryLinks: boolean;

248

directionLinks: boolean;

249

ellipses: boolean;

250

maxSize: number;

251

pageSize: number;

252

rotate: boolean;

253

size: 'sm' | 'lg' | string | null;

254

}

255

```

256

257

### Dropdown Components

258

259

Contextual overlays for displaying lists of links and interactive content.

260

261

#### NgbDropdown

262

263

Main dropdown directive that provides contextual overlays.

264

265

```typescript { .api }

266

@Directive({

267

selector: '[ngbDropdown]',

268

exportAs: 'ngbDropdown'

269

})

270

class NgbDropdown {

271

/** Auto-close behavior: true, false, 'inside', or 'outside' */

272

@Input() autoClose: boolean | 'outside' | 'inside';

273

274

/** Custom class applied to dropdown container */

275

@Input() dropdownClass: string;

276

277

/** Initial open state */

278

@Input('open') _open: boolean;

279

280

/** Preferred placement of dropdown menu */

281

@Input() placement: PlacementArray;

282

283

/** Popper options modifier function */

284

@Input() popperOptions: (options: Partial<Options>) => Partial<Options>;

285

286

/** Container element, currently only supports 'body' */

287

@Input() container: null | 'body';

288

289

/** Positioning behavior: 'dynamic' or 'static' */

290

@Input() display: 'dynamic' | 'static';

291

292

/** Event emitted when dropdown opens or closes */

293

@Output() openChange: EventEmitter<boolean>;

294

295

/** Check if dropdown is open */

296

isOpen(): boolean;

297

298

/** Open the dropdown */

299

open(): void;

300

301

/** Close the dropdown */

302

close(): void;

303

304

/** Toggle dropdown state */

305

toggle(): void;

306

}

307

```

308

309

#### NgbDropdownToggle

310

311

Directive for elements that toggle dropdown on click.

312

313

```typescript { .api }

314

@Directive({

315

selector: '[ngbDropdownToggle]'

316

})

317

class NgbDropdownToggle {

318

nativeElement: HTMLElement;

319

}

320

```

321

322

#### NgbDropdownAnchor

323

324

Directive for elements that anchor dropdown without click handling.

325

326

```typescript { .api }

327

@Directive({

328

selector: '[ngbDropdownAnchor]'

329

})

330

class NgbDropdownAnchor {

331

nativeElement: HTMLElement;

332

}

333

```

334

335

#### NgbDropdownMenu

336

337

Directive that wraps dropdown menu content.

338

339

```typescript { .api }

340

@Directive({

341

selector: '[ngbDropdownMenu]'

342

})

343

class NgbDropdownMenu {

344

menuItems: QueryList<NgbDropdownItem>;

345

nativeElement: HTMLElement;

346

}

347

```

348

349

#### NgbDropdownItem

350

351

Directive for dropdown items with keyboard navigation support.

352

353

```typescript { .api }

354

@Directive({

355

selector: '[ngbDropdownItem]'

356

})

357

class NgbDropdownItem {

358

/** Tab index for keyboard navigation */

359

@Input() tabindex: string | number;

360

361

/** Disabled state */

362

@Input() disabled: boolean;

363

364

nativeElement: HTMLElement;

365

}

366

```

367

368

#### NgbDropdownButtonItem

369

370

Additional directive for button dropdown items.

371

372

```typescript { .api }

373

@Directive({

374

selector: 'button[ngbDropdownItem]'

375

})

376

class NgbDropdownButtonItem {

377

item: NgbDropdownItem;

378

}

379

```

380

381

#### NgbDropdownConfig

382

383

Configuration service for dropdown defaults.

384

385

```typescript { .api }

386

@Injectable({ providedIn: 'root' })

387

class NgbDropdownConfig {

388

autoClose: boolean | 'outside' | 'inside';

389

placement: PlacementArray;

390

popperOptions: (options: Partial<Options>) => Partial<Options>;

391

container: null | 'body';

392

}

393

```

394

395

### Progressbar Components

396

397

Components for displaying progress indicators with various styling options.

398

399

#### NgbProgressbar

400

401

Main progress bar component that provides feedback on task completion.

402

403

```typescript { .api }

404

@Component({

405

selector: 'ngb-progressbar',

406

exportAs: 'ngbProgressbar'

407

})

408

class NgbProgressbar {

409

/** The current value for the progress bar (required) */

410

@Input({ required: true }) value: number;

411

412

/** The maximal value to be displayed (default: 100) */

413

@Input() max: number;

414

415

/** If true, the stripes are animated */

416

@Input() animated: boolean;

417

418

/** The accessible progress bar name */

419

@Input() ariaLabel: string;

420

421

/** If true, the progress bar will be displayed as striped */

422

@Input() striped: boolean;

423

424

/** If true, the current percentage will be shown in xx% format */

425

@Input() showValue: boolean;

426

427

/** Optional text variant type for text color */

428

@Input() textType: string;

429

430

/** The type/color of the progress bar (Bootstrap variants) */

431

@Input() type: string;

432

433

/** The height of the progress bar (accepts CSS values) */

434

@Input() height: string;

435

436

/** Get the current value within the valid range */

437

getValue(): number;

438

439

/** Get the current percentage value */

440

getPercentValue(): number;

441

}

442

```

443

444

#### NgbProgressbarStacked

445

446

Container component for stacked progress bars.

447

448

```typescript { .api }

449

@Component({

450

selector: 'ngb-progressbar-stacked',

451

exportAs: 'ngbProgressbarStacked'

452

})

453

class NgbProgressbarStacked {

454

// Container component - no inputs, only provides stacking context

455

}

456

```

457

458

#### NgbProgressbarConfig

459

460

Configuration service for progressbar defaults.

461

462

```typescript { .api }

463

@Injectable({ providedIn: 'root' })

464

class NgbProgressbarConfig {

465

max: number;

466

animated: boolean;

467

ariaLabel: string;

468

striped: boolean;

469

textType: string;

470

type: string;

471

showValue: boolean;

472

height: string;

473

}

474

```

475

476

### ScrollSpy Components

477

478

Components for automatically updating navigation based on scroll position.

479

480

#### NgbScrollSpy

481

482

Main scrollspy directive that observes fragments and maintains active state.

483

484

```typescript { .api }

485

@Directive({

486

selector: '[ngbScrollSpy]',

487

exportAs: 'ngbScrollSpy'

488

})

489

class NgbScrollSpy {

490

/** Custom process changes function */

491

@Input() processChanges: NgbScrollSpyProcessChanges;

492

493

/** Scroll behavior for programmatic scrolling */

494

@Input() scrollBehavior: 'auto' | 'smooth';

495

496

/** Current active fragment id */

497

get active(): string;

498

499

/** Observable of active fragment changes */

500

get active$(): Observable<string>;

501

502

/** Scroll to a specific fragment */

503

scrollTo(fragment: string | HTMLElement, options?: NgbScrollToOptions): void;

504

}

505

```

506

507

#### NgbScrollSpyItem

508

509

Directive for menu items that link to scrollspy fragments.

510

511

```typescript { .api }

512

@Directive({

513

selector: '[ngbScrollSpyItem]',

514

exportAs: 'ngbScrollSpyItem'

515

})

516

class NgbScrollSpyItem {

517

/** Reference to scroll spy, fragment id, and optional parent */

518

@Input('ngbScrollSpyItem') data: NgbScrollSpy | string | [NgbScrollSpy, string, string?];

519

520

/** The id of the associated fragment */

521

@Input() fragment: string;

522

523

/** The id of parent menu item for nested navigation */

524

@Input() parent: string;

525

526

/** Check if this item is currently active */

527

isActive(): boolean;

528

529

/** Scroll to the associated fragment */

530

scrollTo(): void;

531

}

532

```

533

534

#### NgbScrollSpyMenu

535

536

Directive for menu containers that manage scrollspy items.

537

538

```typescript { .api }

539

@Directive({

540

selector: '[ngbScrollSpyMenu]',

541

exportAs: 'ngbScrollSpyMenu'

542

})

543

class NgbScrollSpyMenu {

544

/** Reference to the scroll spy directive */

545

@Input('ngbScrollSpyMenu') scrollSpy: NgbScrollSpy;

546

547

/** Current active fragment id */

548

get active(): string;

549

550

/** Observable of active fragment changes */

551

get active$(): Observable<string>;

552

553

/** Scroll to a specific fragment */

554

scrollTo(fragment: string | HTMLElement, options?: NgbScrollToOptions): void;

555

}

556

```

557

558

#### NgbScrollSpyFragment

559

560

Directive that marks elements as scrollspy fragments.

561

562

```typescript { .api }

563

@Directive({

564

selector: '[ngbScrollSpyFragment]'

565

})

566

class NgbScrollSpyFragment {

567

/** The unique id of the fragment */

568

@Input('ngbScrollSpyFragment') id: string;

569

}

570

```

571

572

#### NgbScrollSpyService

573

574

Injectable service for global scrollspy functionality.

575

576

```typescript { .api }

577

@Injectable({ providedIn: 'root' })

578

class NgbScrollSpyService {

579

/** Current active fragment id */

580

get active(): string;

581

582

/** Observable of active fragment changes */

583

get active$(): Observable<string>;

584

585

/** Scroll to a specific fragment */

586

scrollTo(fragment: string | HTMLElement, options?: NgbScrollToOptions): void;

587

588

/** Start observing fragments */

589

start(options: NgbScrollSpyOptions): void;

590

591

/** Stop observing fragments */

592

stop(): void;

593

}

594

```

595

596

#### NgbScrollSpyConfig

597

598

Configuration service for scrollspy defaults.

599

600

```typescript { .api }

601

@Injectable({ providedIn: 'root' })

602

class NgbScrollSpyConfig {

603

scrollBehavior: 'auto' | 'smooth';

604

processChanges: NgbScrollSpyProcessChanges;

605

}

606

```

607

608

## Configuration Services

609

610

```typescript { .api }

611

@Injectable({ providedIn: 'root' })

612

class NgbCollapseConfig {

613

/** Default animation setting */

614

animation: boolean;

615

}

616

617

@Injectable({ providedIn: 'root' })

618

class NgbOffcanvasConfig {

619

/** Default backdrop behavior */

620

backdrop: boolean | 'static';

621

622

/** Default keyboard support */

623

keyboard: boolean;

624

625

/** Default position */

626

position: 'start' | 'end' | 'top' | 'bottom';

627

628

/** Default scroll behavior */

629

scroll: boolean;

630

631

/** Default animation setting */

632

animation: boolean;

633

}

634

635

@Injectable({ providedIn: 'root' })

636

class NgbPaginationConfig {

637

/** Default disabled state */

638

disabled: boolean;

639

640

/** Default boundary links setting */

641

boundaryLinks: boolean;

642

643

/** Default direction links setting */

644

directionLinks: boolean;

645

646

/** Default max size */

647

maxSize: number;

648

649

/** Default page size */

650

pageSize: number;

651

652

/** Default rotate setting */

653

rotate: boolean;

654

655

/** Default size */

656

size: 'sm' | 'lg';

657

}

658

```

659

660

## Type Definitions

661

662

```typescript { .api }

663

interface NgbOffcanvasOptions {

664

/** Backdrop behavior */

665

backdrop?: boolean | 'static';

666

667

/** Keyboard support */

668

keyboard?: boolean;

669

670

/** Position of offcanvas */

671

position?: 'start' | 'end' | 'top' | 'bottom';

672

673

/** Allow body scrolling */

674

scroll?: boolean;

675

676

/** Animation setting */

677

animation?: boolean;

678

679

/** CSS class for offcanvas */

680

panelClass?: string;

681

682

/** Container element */

683

container?: string | Element;

684

685

/** Injector for component content */

686

injector?: Injector;

687

}

688

689

enum OffcanvasDismissReasons {

690

/** Offcanvas dismissed by clicking backdrop */

691

BACKDROP_CLICK,

692

693

/** Offcanvas dismissed by pressing ESC key */

694

ESC

695

}

696

```

697

698

## Usage Examples

699

700

### Basic Collapse

701

702

```typescript

703

@Component({

704

template: `

705

<div class="mb-3">

706

<button

707

class="btn btn-primary"

708

(click)="isCollapsed = !isCollapsed">

709

Toggle collapse

710

</button>

711

</div>

712

713

<div [ngbCollapse]="isCollapsed">

714

<div class="card card-body">

715

This content can be collapsed and expanded.

716

<p>More content here...</p>

717

</div>

718

</div>

719

720

<p class="mt-3">Collapsed: {{ isCollapsed }}</p>

721

`

722

})

723

export class BasicCollapseComponent {

724

isCollapsed = false;

725

}

726

```

727

728

### Offcanvas Panel

729

730

```typescript

731

@Component({

732

template: `

733

<button class="btn btn-primary" (click)="openOffcanvas(content)">

734

Open offcanvas

735

</button>

736

737

<ng-template #content let-offcanvas>

738

<div class="offcanvas-header">

739

<h4 class="offcanvas-title">Offcanvas Title</h4>

740

<button type="button" class="btn-close" (click)="offcanvas.dismiss()"></button>

741

</div>

742

743

<div class="offcanvas-body">

744

<p>This is the offcanvas content.</p>

745

<ul>

746

<li>Item 1</li>

747

<li>Item 2</li>

748

<li>Item 3</li>

749

</ul>

750

</div>

751

</ng-template>

752

`

753

})

754

export class BasicOffcanvasComponent {

755

constructor(private offcanvasService: NgbOffcanvas) {}

756

757

openOffcanvas(content: any) {

758

const offcanvasRef = this.offcanvasService.open(content, {

759

position: 'start',

760

backdrop: true,

761

keyboard: true

762

});

763

764

offcanvasRef.result.then((result) => {

765

console.log('Offcanvas closed:', result);

766

}).catch((error) => {

767

console.log('Offcanvas dismissed:', error);

768

});

769

}

770

}

771

```

772

773

### Basic Pagination

774

775

```typescript

776

@Component({

777

template: `

778

<ngb-pagination

779

[(page)]="currentPage"

780

[collectionSize]="totalItems"

781

[pageSize]="itemsPerPage"

782

[maxSize]="5"

783

[rotate]="true"

784

[boundaryLinks]="true"

785

(pageChange)="onPageChange($event)">

786

</ngb-pagination>

787

788

<p>Current page: {{ currentPage }} of {{ totalPages }}</p>

789

<p>Showing items {{ startItem }} - {{ endItem }} of {{ totalItems }}</p>

790

`

791

})

792

export class BasicPaginationComponent {

793

currentPage = 1;

794

totalItems = 200;

795

itemsPerPage = 10;

796

797

get totalPages() {

798

return Math.ceil(this.totalItems / this.itemsPerPage);

799

}

800

801

get startItem() {

802

return (this.currentPage - 1) * this.itemsPerPage + 1;

803

}

804

805

get endItem() {

806

return Math.min(this.currentPage * this.itemsPerPage, this.totalItems);

807

}

808

809

onPageChange(page: number) {

810

console.log('Page changed to:', page);

811

// Load data for the new page

812

}

813

}

814

```

815

816

### Progress Bars

817

818

```typescript

819

@Component({

820

template: `

821

<div class="mb-3">

822

<label>Simple progress bar:</label>

823

<ngb-progressbar

824

[value]="progress"

825

[max]="100"

826

type="success"

827

[showValue]="true">

828

</ngb-progressbar>

829

</div>

830

831

<div class="mb-3">

832

<label>Striped and animated:</label>

833

<ngb-progressbar

834

[value]="progress"

835

[max]="100"

836

type="info"

837

[striped]="true"

838

[animated]="true">

839

</ngb-progressbar>

840

</div>

841

842

<div class="mb-3">

843

<label>Stacked progress bars:</label>

844

<ngb-progressbar-stacked [max]="100">

845

<ngb-progressbar [value]="25" type="success"></ngb-progressbar>

846

<ngb-progressbar [value]="35" type="warning"></ngb-progressbar>

847

<ngb-progressbar [value]="20" type="danger"></ngb-progressbar>

848

</ngb-progressbar-stacked>

849

</div>

850

851

<div class="mb-3">

852

<button class="btn btn-primary me-2" (click)="increaseProgress()">

853

Increase

854

</button>

855

<button class="btn btn-secondary" (click)="resetProgress()">

856

Reset

857

</button>

858

</div>

859

`

860

})

861

export class ProgressBarComponent {

862

progress = 45;

863

864

increaseProgress() {

865

this.progress = Math.min(this.progress + 10, 100);

866

}

867

868

resetProgress() {

869

this.progress = 0;

870

}

871

}

872

```

873

874

### Dropdown Menu

875

876

```typescript

877

@Component({

878

template: `

879

<div ngbDropdown class="d-inline-block">

880

<button class="btn btn-primary" ngbDropdownToggle>

881

Dropdown menu

882

</button>

883

884

<div ngbDropdownMenu>

885

<button ngbDropdownItem (click)="onAction('action1')">

886

Action 1

887

</button>

888

<button ngbDropdownItem (click)="onAction('action2')">

889

Action 2

890

</button>

891

<div class="dropdown-divider"></div>

892

<button ngbDropdownItem [disabled]="true">

893

Disabled action

894

</button>

895

</div>

896

</div>

897

898

<p *ngIf="lastAction" class="mt-3">

899

Last action: {{ lastAction }}

900

</p>

901

`

902

})

903

export class DropdownComponent {

904

lastAction: string = '';

905

906

onAction(action: string) {

907

this.lastAction = action;

908

console.log('Action selected:', action);

909

}

910

}

911

```

912

913

### ScrollSpy Navigation

914

915

```typescript

916

@Component({

917

template: `

918

<div class="row">

919

<div class="col-3">

920

<nav class="nav nav-pills flex-column sticky-top">

921

<a class="nav-link" [class.active]="activeSection === 'section1'"

922

(click)="scrollTo('section1')">Section 1</a>

923

<a class="nav-link" [class.active]="activeSection === 'section2'"

924

(click)="scrollTo('section2')">Section 2</a>

925

<a class="nav-link" [class.active]="activeSection === 'section3'"

926

(click)="scrollTo('section3')">Section 3</a>

927

</nav>

928

</div>

929

930

<div class="col-9">

931

<div ngbScrollSpy

932

[ngbScrollSpy]="['section1', 'section2', 'section3']"

933

(activeChange)="onActiveChange($event)"

934

style="height: 400px; overflow-y: auto;">

935

936

<div id="section1" style="height: 300px; background-color: #f8f9fa;">

937

<h3>Section 1</h3>

938

<p>Content for section 1...</p>

939

</div>

940

941

<div id="section2" style="height: 300px; background-color: #e9ecef;">

942

<h3>Section 2</h3>

943

<p>Content for section 2...</p>

944

</div>

945

946

<div id="section3" style="height: 300px; background-color: #dee2e6;">

947

<h3>Section 3</h3>

948

<p>Content for section 3...</p>

949

</div>

950

</div>

951

</div>

952

</div>

953

`

954

})

955

export class ScrollSpyComponent {

956

activeSection: string = 'section1';

957

958

onActiveChange(activeId: string) {

959

this.activeSection = activeId;

960

}

961

962

scrollTo(sectionId: string) {

963

const element = document.getElementById(sectionId);

964

if (element) {

965

element.scrollIntoView({ behavior: 'smooth' });

966

}

967

}

968

}

969

```