Angular 11项目中Bootstrap 5的提示框无法使用

5
我尝试在一个 Angular 11 项目中使用以下代码来使用 Bootstrap 5.0.2:

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/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
  <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</head>
<body>
  <app-root></app-root>
</body>
</html>

在一个组件中:
<a class="btn btn-primary"
  data-bs-toggle="tooltip"
  data-bs-html="true"
  data-bs-placement="top"
  [title]="myTitle | toHtmlEntity"
  [href]="myUrl">

  {{ myButtonLabel }}
</a>

没有错误信息,但是工具提示无法正常工作。当鼠标悬停在链接上时,标题字符串会显示出来。
你有什么想法我可能忽略了什么?
6个回答

8
为了补充@yatinsingla的答案,请不要忘记添加。
declare var bootstrap: any

在组件类顶部,紧接在import语句之下。

因此您应该有如下代码:

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)
        })       
    }
}

如果需要初始化 Bootstrap 5的popovers弹出框,请在ngOnInit()函数中像tooltip一样添加javascript 初始化代码(可以直接从Bootstrap文档复制)。


谢谢,它对我有用,但是我在Angular CLI终端中遇到了这个错误>>> ERROR ReferenceError: document is not defined at ExtensionComponent.ngOnInit - Asmaa3107

1

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>();
}

这正是我需要的,可以修复 Bootstrap 工具提示的“卡住”行为 :) - Speuline
优美的解决方案。是否有一种优化的方式可以在组件加载和销毁时自动调用此服务?目前我正在从每个组件的ngOnInitngOnDestroy方法中调用enableTooltiphideAllTooltips - Ganesh Bhosale

1

最好的方法是创建一个属性指令

安装Bootstrap

npm install bootstrap

styles.scss中导入Bootstrap 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";

在 angular.json 中导入 Bootstrap Bundle JS -> architect -> build -> options

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

在 `src/typings.d.ts` 中将 `boostrap` 声明为全局变量。如果文件不存在,则创建该文件。
declare var bootstrap: any;

创建一个指令工具提示:

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();
  });
});

src/app/app.module.ts 中声明 Tooltip 指令。
import { TooltipDirective } from './_components/tooltip.directive';

@NgModule({
  declarations: [
    ...
    TooltipDirective
  ]
})

使用以下指令:
<a bTooltip title="Your Message"></a>

现在您将能够使用Tooltip及其所有属性,例如data-bs-placement
我认为通过类似的方法,您可以在Angular中使用大多数Bootstrap组件。

0

1
每次渲染事件后有没有一种解决方案,可以使这段代码在每个组件中只运行一次,以通用的方式工作? - netdjw
我需要检查最好的方法!但是一种方法可能是创建一个服务并在其中添加代码。在每个组件中,在构造函数中实例化该服务以启用此功能。如果有意义的话? - yatinsingla
这是有道理的,但仍然不像最佳实践那样。 - netdjw
由于你正在使用Angular项目,你尝试过使用ng-bootstrap吗?我猜你不需要任何JavaScript/jQuery代码来启用工具提示。它应该开箱即用。 - yatinsingla

0
你可以检查你的 <button> 或者 <a> 标签是否在一个 *ngIf 条件内。在我的情况中就是这样。示例:
<a *ngIf="conditionVariable" [routerLink]="['/home']" class="btn btn-primary btn-sm">BUTTON</a>

或者

<div *ngIf="conditionVariable">
    <a [routerLink]="['/home']" class="btn btn-primary btn-sm">BUTTON</a>
</div>

如果你的代码是这样的,你应该将它替换为类似于以下内容:
<a [hidden]="conditionVariable" [routerLink]="['/home']" class="btn btn-primary btn-sm">BUTTON</a>

或者

<div [hidden]="ConditionVariable">
    <a [routerLink]="['/home']" class="btn btn-primary btn-sm">BUTTON</a>
</div>

0

这里的人们正在询问我们是否需要在实现引导工具提示的所有类中添加该方法。 我认为有几个解决方案可以解决这个问题

  1. 我们可以在应用程序组件中使用路由器事件并订阅它,一旦完成呈现子组件,就运行此逻辑。 例如,在ngOnInit应用程序组件中使用以下代码:

    this.routerEvents.subscribe((event: Event) => { if(event instanceOf NavigationEnd) { Array.from(document.querySelectorAll('button[data-bs- toggle="tooltip"]')) .forEach(tooltipNode => new bootstrap.Tooltip(tooltipNode)) }

    })

  2. 使用指令并在那里使用renderer2和ElementRef进行逻辑处理,但请确保不要使用document和Array,而是使用renderer2和ElementRef。

这里有一个使用指令的示例

       <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);
  }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接