Reputation: 6007
I try to use Bootstrap 5.0.2 in an Angular 11 project with this code:
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<title>My Project</title>
<base href="/">
<meta http-equiv="content-language" content="en-US" />
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</head>
<body>
<app-root></app-root>
</body>
</html>
In a component:
<a class="btn btn-primary"
data-bs-toggle="tooltip"
data-bs-html="true"
data-bs-placement="top"
[title]="myTitle | toHtmlEntity"
[href]="myUrl">
{{ myButtonLabel }}
</a>
No error message, but the tooltip is not working. The title string showed up when the mouse hover the link.
Any idea what I missed?
Upvotes: 5
Views: 12569
Reputation: 1
You can just use this in ngAfterViewInit
. It works for me:
const exampleEl = document.getElementById('tool') as HTMLDivElement;
const tooltip = new bootstrap.Tooltip(exampleEl, {
animation: true,
trigger:"hover",
title:"Need Help?",
})
Upvotes: 0
Reputation: 2120
Best way for this is to create a Attribute Directive
.
Install Bootstrap
npm install bootstrap
Import Bootstrap SCSS in styles.scss
// For Setting Project Specific Bootstrap Variable. Like $primary Color
@import "assets/scss/variables.scss";
// Import Bootstrap
@import "../node_modules/bootstrap/scss/bootstrap.scss";
// App Specific components
@import "assets/scss/app.scss";
Import Bootstrap Bundle JS in angular.json -> architect -> build -> options
"scripts": [
"node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
]
Declare boostrap
as global variable in src/typings.d.ts
.
Create this file if doesn't exists.
declare var bootstrap: any;
Create a directive Tooltip:
src/app/_components/tooltip.directive.ts
import { AfterViewInit, Directive, ElementRef, OnDestroy } from '@angular/core';
@Directive({
selector: '[bTooltip]'
})
export class TooltipDirective implements AfterViewInit, OnDestroy {
private tooltip: any;
constructor(private elementRef: ElementRef) {}
ngAfterViewInit() {
const domElement: HTMLElement = this.elementRef.nativeElement;
this.tooltip = new bootstrap.Tooltip(domElement);
}
ngOnDestroy(): void {
this.tooltip.dispose();
}
}
src/app/_components/tooltip.directive.spec.ts
import { ElementRef } from '@angular/core';
import { TooltipDirective } from './tooltip.directive';
describe('TooltipDirective', () => {
it('should create an instance', () => {
const elementRefMock: ElementRef = {} as ElementRef;
const directive = new TooltipDirective(elementRefMock);
expect(directive).toBeTruthy();
});
});
Declare Tooltip directive in src/app/app.module.ts
:
import { TooltipDirective } from './_components/tooltip.directive';
@NgModule({
declarations: [
...
TooltipDirective
]
})
Use the directive as below:
<a bTooltip title="Your Message"></a>
Now you will be able to use Tooltip with all it's attributes like data-bs-placement
.
I think with similar approach you can use most of the Bootstrap components in Angular.
Upvotes: 2
Reputation: 29
People here are asking whether we need to add that method in all the classes where we implement the bootstrap tooltip. There are a couple of solutions that I think will work
We could use Router Events in the app component and subscribe to that and once we are finished rendering child components then run this logic. e.g in the ngOnInit app component use the below code
this.routerEvents.subscribe((event: Event) => { if(event instanceOf NavigationEnd) { Array.from(document.querySelectorAll('button[data-bs- toggle="tooltip"]')) .forEach(tooltipNode => new bootstrap.Tooltip(tooltipNode)) }
})
use directive and use logic there using renderer2 and ElementRef, but make sure instead of using document and Array just use renderer2 and ElementRef
example here with directive
<button type="button" appTooltip="Tooltip Data" class="btn btn-secondary me-2">
Hover on me
</button>
import { AfterViewInit, Directive, ElementRef, Input, Renderer2 } from '@angular/core';
declare var bootstrap: any;
@Directive({
selector: '[appTooltip]'
})
export class BootstrapTooltipInitDirective implements AfterViewInit {
constructor(private el: ElementRef, private renderer: Renderer2) { }
@Input() placement = 'top';
@Input() appTooltip = '';
ngAfterViewInit(): void {
this.renderer.setAttribute(this.el.nativeElement, 'data-bs-toggle', 'tooltip');
this.renderer.setAttribute(this.el.nativeElement, 'data-bs-placement', this.placement);
this.renderer.setAttribute(this.el.nativeElement, 'title', this.appTooltip);
new bootstrap.Tooltip(this.el.nativeElement);
}
}
Upvotes: 0
Reputation: 371
You could check if your <button>
or <a>
tag is inside an *ngIf
condition. That happened in my case. Example:
<a *ngIf="conditionVariable" [routerLink]="['/home']" class="btn btn-primary btn-sm">BUTTON</a>
or
<div *ngIf="conditionVariable">
<a [routerLink]="['/home']" class="btn btn-primary btn-sm">BUTTON</a>
</div>
In case you have it like this, you should replace it with something like:
<a [hidden]="conditionVariable" [routerLink]="['/home']" class="btn btn-primary btn-sm">BUTTON</a>
or
<div [hidden]="ConditionVariable">
<a [routerLink]="['/home']" class="btn btn-primary btn-sm">BUTTON</a>
</div>
Upvotes: 0
Reputation: 176
package.json
"@popperjs/core": "^2.10.2",
"bootstrap": "^5.1.3",
angular.json
"scripts": [
"node_modules/@popperjs/core/dist/umd/popper.min.js",
"node_modules/bootstrap/dist/js/bootstrap.min.js",
],
app.service.ts
declare var bootstrap: any;
private tooltipList = new Array<any>();
enableTooltip() {
// Bootstrap tooltip initialization
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
const tooltipListNewTooltips = tooltipTriggerList.map(tooltipTriggerEl => {
return new bootstrap.Tooltip(tooltipTriggerEl);
});
this.tooltipList.push(...tooltipListNewTooltips);
}
hideAllTooltips() {
this.tooltipList;
for (const tooltip of this.tooltipList) {
tooltip.dispose();
}
this.tooltipList = new Array<any>();
}
Upvotes: 1
Reputation: 156
To add on @yatinsingla's answer, don't forget to add
declare var bootstrap: any
at the top of your component class, just below the imports.
So you have:
import {} from "....";
....
declare var bootstrap: any;
export class YourComponent implements OnInit, <other interfaces> {
ngOnInit(): void {
// Bootstrap tooltip initialization
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl)
})
}
}
If you need to initizalize bootstrap 5's popovers, add the javascript initialization code (just copy it from the bootstrap's docs) in the ngOnInit() function the same was as for the tooltips.
Upvotes: 9
Reputation: 442
try writing this code in your ts file:
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl)
})
source: https://getbootstrap.com/docs/5.0/components/tooltips/#example-enable-tooltips-everywhere
Upvotes: 0