Search code examples
angulartypescriptbootstrap-5popper.js

How to use Bootstrap components in an Angular app without a third party module?


I'm trying to enable Bootstrap 5.3 Tooltips in my Angular 17 app.

In angular.json I've included bootstrap.bundle.min.js, which has PopperJS baked in.

"scripts": [
  "node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
]

I'm using the example code provided by Bootstrap in the official documentation for enabling the tooltips: https://getbootstrap.com/docs/5.3/components/tooltips/#enable-tooltips

Their code throws an error on line 16 of my app.component.ts file...

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  title = 'identity-verification-ui';

  onInit() {
    const tooltipTriggerList = document.querySelectorAll(
      '[data-bs-toggle="tooltip"]'
    );
    const tooltipList = [...tooltipTriggerList].map(
      (tooltipTriggerEl) => new bootstrap.Tooltip(tooltipTriggerEl) // <-- line 16
    );
  }
}

The error is Cannot find name 'bootstrap'. ts (2304). Obviously, the bootstrap class is not available from app.component.ts.

enter image description here

How do I make new bootstrap available within app.component.ts? Is app.component.ts not the correct place for enabling Bootstrap components across the entire app? Is there a more preferable way to do this?

I want to avoid loading jQuery.

I want to avoid using a third-party npm module.


Solution

  • Update thanks to Kirkland, that remember me "not use any if you can avoid it" I change declaring as HTMLElement instead of any

    if you install @types/bootstrap

    npm i @types/bootstrap
    

    Just import only Tooltip in your component

    import { Tooltip } from 'bootstrap';
    

    And in ngOnInit

    ngOnInit() {
      const tooltips:HTMLElement[]=[].slice.call(
                document.querySelectorAll('[data-bs-toggle="tooltip"]'))
      tooltips.map((x:HTMLElement)=>new Tooltip(x))
    }
    

    a stackblitz

    Update2 using a directive with a selector like [data-bs-toggle="tooltip"] makes that each element with this attribute become in a "super" element. So we can create:

    import { Directive, ElementRef } from '@angular/core';
    import { Tooltip } from 'bootstrap';
    
    @Directive({
      selector: '[data-bs-toggle="tooltip"]',
      standalone: true
    })
    export class TooltipDirective {
      constructor(elementRef: ElementRef) {
        new Tooltip(elementRef.nativeElement);
      }
    }
    

    Each standalone component that import this directive makes that the toolTip work.

    To enable it app-wide remove standalone: true and import into @NgModule...

    import { TooltipDirective } from './path/to/tooltip.directive';
    
    @NgModule({
      ...
      declarations: [
        ...
        TooltipDirective,
        ...
      ],
      ...
    });