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

utilities-infrastructure.mddocs/

0

# Utilities & Infrastructure

1

2

Core utilities for positioning, theming, date manipulation, component loading, and other infrastructure functionality.

3

4

## Capabilities

5

6

### Positioning

7

8

Advanced positioning calculations for overlays, tooltips, dropdowns, and other positioned elements.

9

10

```typescript { .api }

11

/**

12

* Service for element positioning calculations

13

*/

14

@Injectable()

15

class PositioningService {

16

/** Position target element relative to host element */

17

position(

18

hostElement: HTMLElement,

19

targetElement: HTMLElement,

20

placement?: string,

21

appendToBody?: boolean

22

): { top: number; left: number };

23

24

/** Get available positions for element */

25

getAvailablePositions(

26

hostElement: HTMLElement,

27

targetElement: HTMLElement

28

): string[];

29

30

/** Check if element fits in viewport */

31

checkFit(

32

element: HTMLElement,

33

placement: string

34

): boolean;

35

36

/** Auto position element based on available space */

37

autoPosition(

38

hostElement: HTMLElement,

39

targetElement: HTMLElement,

40

preferredPlacement?: string

41

): { top: number; left: number; placement: string };

42

}

43

44

/**

45

* Core positioning utility class

46

*/

47

class Positioning {

48

/** Get element position relative to document */

49

static position(element: HTMLElement, round?: boolean): { width: number; height: number; top: number; left: number };

50

51

/** Get element offset */

52

static offset(element: HTMLElement, round?: boolean): { width: number; height: number; top: number; left: number };

53

54

/** Position elements */

55

static positionElements(

56

hostElement: HTMLElement,

57

targetElement: HTMLElement,

58

placement: string,

59

appendToBody?: boolean,

60

options?: PositioningOptions

61

): { top: number; left: number };

62

}

63

64

/**

65

* Positioning configuration options

66

*/

67

interface PositioningOptions {

68

/** Offset from host element */

69

offset?: number;

70

/** Allow flipping placement */

71

allowFlip?: boolean;

72

/** Viewport boundaries */

73

boundary?: 'viewport' | 'window' | HTMLElement;

74

/** Placement modifiers */

75

modifiers?: PositioningModifier[];

76

}

77

78

/**

79

* Positioning modifier interface

80

*/

81

interface PositioningModifier {

82

/** Modifier name */

83

name: string;

84

/** Modifier options */

85

options?: any;

86

/** Modifier function */

87

fn?: (data: any, options: any) => any;

88

}

89

90

/**

91

* Available Bootstrap positioning options

92

*/

93

type AvailableBSPositions =

94

| 'top' | 'bottom' | 'left' | 'right'

95

| 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'

96

| 'left-top' | 'left-bottom' | 'right-top' | 'right-bottom';

97

98

/**

99

* Bootstrap 5 placement options

100

*/

101

type PlacementForBs5 =

102

| 'auto' | 'auto-start' | 'auto-end'

103

| 'top' | 'top-start' | 'top-end'

104

| 'bottom' | 'bottom-start' | 'bottom-end'

105

| 'right' | 'right-start' | 'right-end'

106

| 'left' | 'left-start' | 'left-end';

107

108

/**

109

* Utility functions for positioning

110

*/

111

declare function positionElements(

112

hostElement: HTMLElement,

113

targetElement: HTMLElement,

114

placement: string,

115

appendToBody?: boolean

116

): { top: number; left: number };

117

118

declare function checkMargins(margin: string | number): { top: number; right: number; bottom: number; left: number };

119

```

120

121

**Usage Example:**

122

123

```typescript

124

import { PositioningService, positionElements } from 'ngx-bootstrap/positioning';

125

126

@Component({

127

template: `

128

<button #hostBtn class="btn btn-primary" (click)="showTooltip()">

129

Host Element

130

</button>

131

132

<div #tooltipEl class="custom-tooltip" [style.display]="tooltipVisible ? 'block' : 'none'">

133

Custom positioned tooltip

134

</div>

135

`,

136

providers: [PositioningService]

137

})

138

export class PositioningExampleComponent {

139

@ViewChild('hostBtn') hostButton: ElementRef;

140

@ViewChild('tooltipEl') tooltipElement: ElementRef;

141

142

tooltipVisible = false;

143

144

constructor(private positioning: PositioningService) {}

145

146

showTooltip() {

147

this.tooltipVisible = true;

148

149

// Position using service

150

const position = this.positioning.position(

151

this.hostButton.nativeElement,

152

this.tooltipElement.nativeElement,

153

'top'

154

);

155

156

// Apply position

157

const tooltip = this.tooltipElement.nativeElement;

158

tooltip.style.top = position.top + 'px';

159

tooltip.style.left = position.left + 'px';

160

161

// Alternative: Use utility function

162

const utilityPosition = positionElements(

163

this.hostButton.nativeElement,

164

this.tooltipElement.nativeElement,

165

'bottom',

166

true

167

);

168

169

console.log('Service position:', position);

170

console.log('Utility position:', utilityPosition);

171

}

172

}

173

```

174

175

### Theme & Version Management

176

177

Utilities for managing Bootstrap theme versions and component styling.

178

179

```typescript { .api }

180

/**

181

* Set Bootstrap theme version

182

*/

183

declare function setTheme(theme: AvailableBsVersions): void;

184

185

/**

186

* Get current Bootstrap version information

187

*/

188

declare function getBsVer(): IBsVersion;

189

190

/**

191

* Current Bootstrap version information

192

*/

193

declare const currentBsVersion: IBsVersion;

194

195

/**

196

* Bootstrap version interface

197

*/

198

interface IBsVersion {

199

/** Is Bootstrap 3 */

200

isBs3: boolean;

201

/** Is Bootstrap 4 */

202

isBs4: boolean;

203

/** Is Bootstrap 5 */

204

isBs5: boolean;

205

}

206

207

/**

208

* Available Bootstrap versions

209

*/

210

type AvailableBsVersions = 'bs3' | 'bs4' | 'bs5';

211

212

/**

213

* Bootstrap version configurations

214

*/

215

interface BsVersions {

216

[key: string]: IBsVersion;

217

}

218

```

219

220

**Usage Example:**

221

222

```typescript

223

import { setTheme, getBsVer, currentBsVersion } from 'ngx-bootstrap/utils';

224

225

@Component({

226

template: `

227

<div class="version-info">

228

<h5>Current Bootstrap Version</h5>

229

<div class="alert alert-info">

230

<div *ngIf="version.isBs3">Bootstrap 3 is active</div>

231

<div *ngIf="version.isBs4">Bootstrap 4 is active</div>

232

<div *ngIf="version.isBs5">Bootstrap 5 is active</div>

233

</div>

234

235

<div class="btn-group" role="group">

236

<button class="btn btn-outline-primary" (click)="switchTheme('bs3')">

237

Bootstrap 3

238

</button>

239

<button class="btn btn-outline-primary" (click)="switchTheme('bs4')">

240

Bootstrap 4

241

</button>

242

<button class="btn btn-outline-primary" (click)="switchTheme('bs5')">

243

Bootstrap 5

244

</button>

245

</div>

246

</div>

247

`

248

})

249

export class ThemeManagerComponent implements OnInit {

250

version: IBsVersion;

251

252

ngOnInit() {

253

this.version = getBsVer();

254

console.log('Current version:', currentBsVersion);

255

}

256

257

switchTheme(theme: AvailableBsVersions) {

258

setTheme(theme);

259

this.version = getBsVer();

260

console.log('Switched to:', theme, this.version);

261

}

262

}

263

```

264

265

### Trigger Management

266

267

Advanced trigger handling for events, outside clicks, and keyboard interactions.

268

269

```typescript { .api }

270

/**

271

* Advanced trigger handling with multiple options

272

*/

273

declare function listenToTriggersV2(

274

renderer: Renderer2,

275

options: TriggerOptions

276

): () => void;

277

278

/**

279

* Register outside click detection

280

*/

281

declare function registerOutsideClick(

282

renderer: Renderer2,

283

options: OutsideClickOptions

284

): () => void;

285

286

/**

287

* Register escape key handling

288

*/

289

declare function registerEscClick(

290

renderer: Renderer2,

291

options: EscClickOptions

292

): () => void;

293

294

/**

295

* Trigger configuration options

296

*/

297

interface TriggerOptions {

298

/** Target element */

299

target: HTMLElement;

300

/** Trigger events */

301

triggers: string;

302

/** Show callback */

303

show: () => void;

304

/** Hide callback */

305

hide: () => void;

306

/** Toggle callback */

307

toggle?: () => void;

308

}

309

310

/**

311

* Outside click options

312

*/

313

interface OutsideClickOptions {

314

/** Target element */

315

targets: HTMLElement[];

316

/** Outside click callback */

317

outsideClick: () => void;

318

/** Exclude elements */

319

exclude?: HTMLElement[];

320

}

321

322

/**

323

* Escape click options

324

*/

325

interface EscClickOptions {

326

/** Escape key callback */

327

escClick: () => void;

328

}

329

330

/**

331

* Trigger utility class

332

*/

333

class Trigger {

334

/** Parse trigger string */

335

static parseTriggers(triggers: string): string[];

336

/** Support manual triggers */

337

static isManual(triggers: string): boolean;

338

}

339

```

340

341

**Usage Example:**

342

343

```typescript

344

import {

345

listenToTriggersV2,

346

registerOutsideClick,

347

registerEscClick

348

} from 'ngx-bootstrap/utils';

349

350

@Component({

351

template: `

352

<button #triggerBtn class="btn btn-primary">

353

Custom Trigger Element

354

</button>

355

356

<div #dropdown class="custom-dropdown" [style.display]="isOpen ? 'block' : 'none'">

357

<div class="dropdown-content">

358

Custom dropdown content

359

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

360

Close

361

</button>

362

</div>

363

</div>

364

`

365

})

366

export class CustomTriggerComponent implements OnInit, OnDestroy {

367

@ViewChild('triggerBtn') triggerButton: ElementRef;

368

@ViewChild('dropdown') dropdown: ElementRef;

369

370

isOpen = false;

371

private unsubscribeTriggers: () => void;

372

private unsubscribeOutsideClick: () => void;

373

private unsubscribeEscClick: () => void;

374

375

constructor(private renderer: Renderer2) {}

376

377

ngOnInit() {

378

// Setup advanced triggers

379

this.unsubscribeTriggers = listenToTriggersV2(this.renderer, {

380

target: this.triggerButton.nativeElement,

381

triggers: 'click hover:500',

382

show: () => this.showDropdown(),

383

hide: () => this.hideDropdown(),

384

toggle: () => this.toggleDropdown()

385

});

386

387

// Setup outside click

388

this.unsubscribeOutsideClick = registerOutsideClick(this.renderer, {

389

targets: [this.triggerButton.nativeElement, this.dropdown.nativeElement],

390

outsideClick: () => this.hideDropdown()

391

});

392

393

// Setup escape key

394

this.unsubscribeEscClick = registerEscClick(this.renderer, {

395

escClick: () => this.hideDropdown()

396

});

397

}

398

399

ngOnDestroy() {

400

if (this.unsubscribeTriggers) this.unsubscribeTriggers();

401

if (this.unsubscribeOutsideClick) this.unsubscribeOutsideClick();

402

if (this.unsubscribeEscClick) this.unsubscribeEscClick();

403

}

404

405

showDropdown() {

406

this.isOpen = true;

407

}

408

409

hideDropdown() {

410

this.isOpen = false;

411

}

412

413

toggleDropdown() {

414

this.isOpen = !this.isOpen;

415

}

416

417

closeDropdown() {

418

this.hideDropdown();

419

}

420

}

421

```

422

423

### Component Loading

424

425

Dynamic component loading and management utilities for programmatic component creation.

426

427

```typescript { .api }

428

/**

429

* Component loader for dynamic component creation

430

*/

431

class ComponentLoader<T> {

432

/** Provide component to load */

433

provide(component: ComponentType<T>): ComponentLoader<T>;

434

435

/** Set container for component */

436

to(container?: string | ElementRef): ComponentLoader<T>;

437

438

/** Configure positioning */

439

position(opts?: PositioningOptions): ComponentLoader<T>;

440

441

/** Show component */

442

show(opts?: ComponentLoaderOptions): ComponentRef<T>;

443

444

/** Hide component */

445

hide(): ComponentLoader<T>;

446

447

/** Toggle component visibility */

448

toggle(): ComponentLoader<T>;

449

450

/** Dispose of component */

451

dispose(): void;

452

453

/** Get component instance */

454

getInstance(): ComponentRef<T>;

455

456

/** Check if component is shown */

457

isShown(): boolean;

458

}

459

460

/**

461

* Factory for creating component loaders

462

*/

463

@Injectable()

464

class ComponentLoaderFactory {

465

/** Create component loader */

466

createLoader<T>(

467

elementRef: ElementRef,

468

viewContainerRef: ViewContainerRef,

469

renderer: Renderer2

470

): ComponentLoader<T>;

471

}

472

473

/**

474

* Reference to loaded component

475

*/

476

class BsComponentRef<T> {

477

/** Template reference */

478

templateRef?: TemplateRef<T>;

479

/** View container reference */

480

viewContainer?: ViewContainerRef;

481

/** Component location */

482

location?: ElementRef;

483

484

/** Hide component */

485

hide(): void;

486

/** Show component */

487

show(): void;

488

/** Toggle component */

489

toggle(): void;

490

}

491

492

/**

493

* Reference to component content

494

*/

495

class ContentRef {

496

/** Nodes collection */

497

nodes: any[];

498

/** View reference */

499

viewRef?: ViewRef;

500

/** Component reference */

501

componentRef?: ComponentRef<any>;

502

503

/** Detach view */

504

detach(): void;

505

/** Attach view */

506

attach(): void;

507

}

508

509

/**

510

* Component loader options

511

*/

512

interface ComponentLoaderOptions {

513

/** Initial state for component */

514

initialState?: { [key: string]: any };

515

/** Providers for component */

516

providers?: StaticProvider[];

517

/** Injector for component */

518

injector?: Injector;

519

}

520

```

521

522

**Usage Example:**

523

524

```typescript

525

import {

526

ComponentLoaderFactory,

527

ComponentLoader,

528

BsComponentRef

529

} from 'ngx-bootstrap/component-loader';

530

531

// Dynamic component to load

532

@Component({

533

template: `

534

<div class="alert alert-info">

535

<h5>{{title}}</h5>

536

<p>{{message}}</p>

537

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

538

{{actionText}}

539

</button>

540

</div>

541

`

542

})

543

export class DynamicAlertComponent {

544

title = 'Dynamic Alert';

545

message = 'This component was loaded dynamically';

546

actionText = 'OK';

547

548

action() {

549

console.log('Dynamic component action triggered');

550

}

551

}

552

553

@Component({

554

template: `

555

<div class="component-loader-demo">

556

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

557

Load Dynamic Component

558

</button>

559

560

<button class="btn btn-success ml-2" (click)="showComponent()" [disabled]="!componentLoader">

561

Show Component

562

</button>

563

564

<button class="btn btn-warning ml-2" (click)="hideComponent()" [disabled]="!componentLoader">

565

Hide Component

566

</button>

567

568

<button class="btn btn-danger ml-2" (click)="disposeComponent()" [disabled]="!componentLoader">

569

Dispose Component

570

</button>

571

572

<!-- Container for dynamic component -->

573

<div #componentContainer class="mt-3"></div>

574

</div>

575

`

576

})

577

export class ComponentLoaderDemoComponent {

578

@ViewChild('componentContainer') containerRef: ElementRef;

579

580

private componentLoader: ComponentLoader<DynamicAlertComponent>;

581

582

constructor(

583

private elementRef: ElementRef,

584

private viewContainerRef: ViewContainerRef,

585

private renderer: Renderer2,

586

private componentLoaderFactory: ComponentLoaderFactory

587

) {}

588

589

loadComponent() {

590

// Create component loader

591

this.componentLoader = this.componentLoaderFactory

592

.createLoader<DynamicAlertComponent>(

593

this.elementRef,

594

this.viewContainerRef,

595

this.renderer

596

);

597

598

// Configure and show component

599

const componentRef = this.componentLoader

600

.provide(DynamicAlertComponent)

601

.to(this.containerRef)

602

.show({

603

initialState: {

604

title: 'Dynamically Loaded',

605

message: 'This component was created using ComponentLoader',

606

actionText: 'Close'

607

}

608

});

609

610

// Access component instance

611

if (componentRef && componentRef.instance) {

612

componentRef.instance.action = () => {

613

this.hideComponent();

614

};

615

}

616

}

617

618

showComponent() {

619

if (this.componentLoader) {

620

this.componentLoader.show();

621

}

622

}

623

624

hideComponent() {

625

if (this.componentLoader) {

626

this.componentLoader.hide();

627

}

628

}

629

630

disposeComponent() {

631

if (this.componentLoader) {

632

this.componentLoader.dispose();

633

this.componentLoader = null;

634

}

635

}

636

}

637

```

638

639

### Date/Time Utilities (Chronos)

640

641

Comprehensive date and time manipulation library with extensive functionality.

642

643

```typescript { .api }

644

/**

645

* Date manipulation functions

646

*/

647

declare function add(date: Date, amount: number, unit: TimeUnit): Date;

648

declare function subtract(date: Date, amount: number, unit: TimeUnit): Date;

649

declare function parseDate(input: string, format?: string, locale?: string): Date;

650

declare function formatDate(date: Date, format: string, locale?: string): string;

651

declare function utcAsLocal(date: Date): Date;

652

653

/**

654

* Date getters

655

*/

656

declare function getDay(date: Date): number;

657

declare function getMonth(date: Date): number;

658

declare function getFullYear(date: Date): number;

659

declare function isFirstDayOfWeek(date: Date, firstDayOfWeek: number): boolean;

660

declare function isSameYear(date1: Date, date2: Date): boolean;

661

declare function isSameDay(date1: Date, date2: Date): boolean;

662

declare function isSameMonth(date1: Date, date2: Date): boolean;

663

declare function getFirstDayOfMonth(date: Date): Date;

664

665

/**

666

* Date comparisons

667

*/

668

declare function isAfter(date1: Date, date2: Date): boolean;

669

declare function isBefore(date1: Date, date2: Date): boolean;

670

declare function isSame(date1: Date, date2: Date, unit?: TimeUnit): boolean;

671

declare function isDisabledDay(

672

date: Date,

673

daysDisabled: number[],

674

minDate?: Date,

675

maxDate?: Date

676

): boolean;

677

678

/**

679

* Date setters

680

*/

681

declare function shiftDate(date: Date, amount: number, unit: TimeUnit): Date;

682

declare function setFullDate(date: Date, year: number, month: number, day: number): Date;

683

684

/**

685

* Start/End operations

686

*/

687

declare function startOf(date: Date, unit: TimeUnit): Date;

688

declare function endOf(date: Date, unit: TimeUnit): Date;

689

690

/**

691

* Validation functions

692

*/

693

declare function isArray(input: any): boolean;

694

declare function isDate(input: any): boolean;

695

declare function isDateValid(date: Date): boolean;

696

697

/**

698

* Locale management

699

*/

700

declare function listLocales(): string[];

701

declare function getLocale(key?: string): any;

702

declare function updateLocale(key: string, values: any): void;

703

declare function defineLocale(key: string, config: any): void;

704

declare function getSetGlobalLocale(key?: string): string;

705

706

/**

707

* Locale data class

708

*/

709

class LocaleData {

710

/** Locale abbreviation */

711

abbr: string;

712

/** Month names */

713

months: string[];

714

/** Short month names */

715

monthsShort: string[];

716

/** Weekday names */

717

weekdays: string[];

718

/** Short weekday names */

719

weekdaysShort: string[];

720

/** Minimal weekday names */

721

weekdaysMin: string[];

722

}

723

724

/**

725

* Time units enumeration

726

*/

727

type TimeUnit = 'year' | 'quarter' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond';

728

```

729

730

**Usage Example:**

731

732

```typescript

733

import {

734

add,

735

subtract,

736

parseDate,

737

formatDate,

738

isSameDay,

739

startOf,

740

endOf,

741

defineLocale,

742

getLocale

743

} from 'ngx-bootstrap/chronos';

744

import { esLocale } from 'ngx-bootstrap/locale';

745

746

@Component({

747

template: `

748

<div class="chronos-demo">

749

<h5>Date Manipulation</h5>

750

751

<div class="mb-3">

752

<label>Current Date: {{currentDate | date:'medium'}}</label>

753

</div>

754

755

<div class="mb-3">

756

<label>Add 7 days: {{futureDate | date:'medium'}}</label>

757

</div>

758

759

<div class="mb-3">

760

<label>Subtract 1 month: {{pastDate | date:'medium'}}</label>

761

</div>

762

763

<div class="mb-3">

764

<label>Start of month: {{monthStart | date:'medium'}}</label>

765

</div>

766

767

<div class="mb-3">

768

<label>End of month: {{monthEnd | date:'medium'}}</label>

769

</div>

770

771

<div class="mb-3">

772

<label>Custom format: {{customFormatted}}</label>

773

</div>

774

775

<div class="mb-3">

776

<label>Spanish locale: {{spanishFormatted}}</label>

777

</div>

778

779

<div class="form-group">

780

<label for="dateInput">Parse Date:</label>

781

<input

782

type="text"

783

class="form-control"

784

id="dateInput"

785

[(ngModel)]="dateInput"

786

(input)="parseInputDate()"

787

placeholder="YYYY-MM-DD">

788

<small class="form-text text-muted">

789

Parsed: {{parsedDate | date:'medium'}}

790

</small>

791

</div>

792

</div>

793

`

794

})

795

export class ChronosExampleComponent implements OnInit {

796

currentDate = new Date();

797

futureDate: Date;

798

pastDate: Date;

799

monthStart: Date;

800

monthEnd: Date;

801

customFormatted: string;

802

spanishFormatted: string;

803

804

dateInput = '2023-12-25';

805

parsedDate: Date;

806

807

ngOnInit() {

808

// Date manipulation

809

this.futureDate = add(this.currentDate, 7, 'day');

810

this.pastDate = subtract(this.currentDate, 1, 'month');

811

812

// Start/end operations

813

this.monthStart = startOf(this.currentDate, 'month');

814

this.monthEnd = endOf(this.currentDate, 'month');

815

816

// Custom formatting

817

this.customFormatted = formatDate(this.currentDate, 'dddd, MMMM Do YYYY');

818

819

// Setup Spanish locale

820

defineLocale('es', esLocale);

821

this.spanishFormatted = formatDate(this.currentDate, 'dddd, MMMM Do YYYY', 'es');

822

823

// Parse initial date

824

this.parseInputDate();

825

826

// Demonstrate comparisons

827

this.demonstrateComparisons();

828

}

829

830

parseInputDate() {

831

try {

832

this.parsedDate = parseDate(this.dateInput, 'YYYY-MM-DD');

833

} catch (error) {

834

console.log('Invalid date format');

835

this.parsedDate = null;

836

}

837

}

838

839

demonstrateComparisons() {

840

const today = new Date();

841

const tomorrow = add(today, 1, 'day');

842

843

console.log('Is same day?', isSameDay(today, tomorrow)); // false

844

console.log('Is tomorrow after today?', isAfter(tomorrow, today)); // true

845

console.log('Is today before tomorrow?', isBefore(today, tomorrow)); // true

846

}

847

}

848

```

849

850

### General Utilities

851

852

Additional utility functions and classes for common operations.

853

854

```typescript { .api }

855

/**

856

* Linked list implementation

857

*/

858

class LinkedList<T> {

859

/** Add item to list */

860

add(item: T, index?: number): void;

861

/** Remove item from list */

862

remove(index: number): void;

863

/** Get item at index */

864

get(index: number): T;

865

/** Get list length */

866

length(): number;

867

/** Convert to array */

868

toArray(): T[];

869

}

870

871

/**

872

* General utility functions

873

*/

874

class Utils {

875

/** Reflow DOM element */

876

static reflow(element: HTMLElement): void;

877

/** Get computed style */

878

static getComputedStyle(element: HTMLElement): CSSStyleDeclaration;

879

/** Check if element is visible */

880

static isVisible(element: HTMLElement): boolean;

881

}

882

883

/**

884

* Change detection decorator

885

*/

886

declare function OnChange(): PropertyDecorator;

887

888

/**

889

* Warning utility that shows message only once

890

*/

891

declare function warnOnce(message: string): void;

892

893

/**

894

* Browser object facades

895

*/

896

declare const window: Window;

897

declare const document: Document;

898

```

899

900

**Usage Example:**

901

902

```typescript

903

import { LinkedList, Utils, warnOnce } from 'ngx-bootstrap/utils';

904

905

@Component({

906

template: `

907

<div class="utils-demo">

908

<h5>Utility Functions Demo</h5>

909

910

<div class="mb-3">

911

<button class="btn btn-primary" (click)="addToList()">Add to List</button>

912

<button class="btn btn-secondary ml-2" (click)="removeFromList()">Remove Last</button>

913

<button class="btn btn-info ml-2" (click)="showListContents()">Show List</button>

914

</div>

915

916

<div class="mb-3">

917

<button class="btn btn-warning" (click)="triggerWarning()">Trigger Warning</button>

918

<button class="btn btn-success ml-2" (click)="checkVisibility()" #visibilityBtn>Check Visibility</button>

919

</div>

920

921

<div class="alert alert-info" *ngIf="listContents.length > 0">

922

<strong>List Contents:</strong>

923

<ul class="mb-0">

924

<li *ngFor="let item of listContents">{{item}}</li>

925

</ul>

926

</div>

927

</div>

928

`

929

})

930

export class UtilsExampleComponent {

931

@ViewChild('visibilityBtn') visibilityButton: ElementRef;

932

933

private myList = new LinkedList<string>();

934

listContents: string[] = [];

935

private itemCounter = 1;

936

937

addToList() {

938

const item = `Item ${this.itemCounter++}`;

939

this.myList.add(item);

940

this.updateListContents();

941

}

942

943

removeFromList() {

944

if (this.myList.length() > 0) {

945

this.myList.remove(this.myList.length() - 1);

946

this.updateListContents();

947

}

948

}

949

950

showListContents() {

951

this.updateListContents();

952

console.log('Current list:', this.listContents);

953

}

954

955

private updateListContents() {

956

this.listContents = this.myList.toArray();

957

}

958

959

triggerWarning() {

960

warnOnce('This warning will only appear once per session');

961

}

962

963

checkVisibility() {

964

if (this.visibilityButton) {

965

const isVisible = Utils.isVisible(this.visibilityButton.nativeElement);

966

const computedStyle = Utils.getComputedStyle(this.visibilityButton.nativeElement);

967

968

console.log('Button is visible:', isVisible);

969

console.log('Button computed style:', computedStyle);

970

971

// Demonstrate reflow

972

Utils.reflow(this.visibilityButton.nativeElement);

973

}

974

}

975

}

976

```