[英]Angular 11 Universal and Bootstrap 5 Toast not working- new bootstrap TS2304: Cannot find name 'bootstrap', crushed
I work with Angular 11 Universal - server side rendering.我使用 Angular 11 Universal - 服务器端渲染。 I'm trying to implement Bootstrap 5 toasts (css works well), but it doesn't understand class new bootstrap:
我正在尝试实现 Bootstrap 5 toasts(css 运行良好),但它不理解 class 新的引导程序:
angular.json - it's imported properly angular.json - 正确导入
"styles": [ "src/styles.scss", "node_modules/bootstrap/dist/css/bootstrap.min.css" ], "scripts": [ "node_modules/@popperjs/core/dist/umd/popper.min.js", "node_modules/bootstrap/dist/js/bootstrap.min.js" ]
package.json package.json
"@angular/platform-browser": "~11.2.7", "@angular/platform-browser-dynamic": "~11.2.7", "@angular/platform-server": "~11.2.7", "@angular/router": "~11.2.7", "@nguniversal/express-engine": "^11.2.1", "@popperjs/core": "^2.9.2", "bootstrap": "^5.0.0-beta3", "express": "^4.15.2", "popper.js": "^1.16.1",
I was trying to implement toasts with initial JS code:我试图用初始 JS 代码实现 toasts:
import { AfterViewInit, Component, ElementRef, EventEmitter, Inject, Input, OnInit, Output, PLATFORM_ID, ViewChild } from '@angular/core'; import { Toast } from '../../../../../node_modules/bootstrap/dist/js/bootstrap.min.js' import {isPlatformBrowser} from "@angular/common"; @Component({ selector: 'app-toast', templateUrl: './toast.component.html', styleUrls: ['./toast.component.scss'] }) export class ToastComponent implements OnInit, AfterViewInit { @Output() closeHit: EventEmitter<boolean> = new EventEmitter<boolean>(); // @Input() title: string = "Toast"; @Input() message: string = 'Enter message here'; @ViewChild('toast') toast: ElementRef<HTMLDivElement> constructor(@Inject(PLATFORM_ID) private platformId: Object) { if (isPlatformBrowser(this.platformId)) { // var toastElList = [].slice.call(document.querySelectorAll('.toast')) // var toastList = toastElList.map(function (toastEl) { return new bootstrap.Toast(this.toast, {}) // }) new Toast(this.toast); // Array.from(document.querySelectorAll('.toast')) //.forEach(toastNode => new Toast(toastNode)) } } ngOnInit(): void { } ngAfterViewInit() { } }
But it don't understand class bootstrap - in new bootstrap TS2304: Cannot find name 'bootstrap'.但它不理解 class bootstrap - 在新的 bootstrap TS2304 中:找不到名称“bootstrap”。
2 variant with importing toast directly from bootstrap.js is breaking the app new Toast(this.toast); 2 直接从 bootstrap.js 导入 toast 的变体破坏了应用程序 new Toast(this.toast);
ReferenceError: document is not defined A server error has occurred. ReferenceError: document is not defined 发生服务器错误。 node exited with 1 code.
节点以 1 个代码退出。 connect ECONNREFUSED 127.0.0.1:62043 npm ERR.
连接 ECONNREFUSED 127.0.0.1:62043 npm 错误。 code ELIFECYCLE npm ERR.
代码 ELIFECYCLE npm 错误。 errno 1 npm ERR: client@0:0.0 dev:ssr:
ng run client:serve-ssr
npm ERR! errno 1 npm ERR: client@0:0.0 dev:ssr:
ng run client:serve-ssr
npm ERR! Exit status 1退出状态 1
Please, help, Is there any way to use Bootstrap 5 functionality for toasts?求助,有什么方法可以使用 Bootstrap 5 功能进行吐司吗? modals in Angular Universal?
Angular 通用模态?
Angular 12 & Bootstrap 5.TS Angular 12 & 引导程序 5.TS
@ViewChild('myToast',{static:true}) toastEl!: ElementRef<HTMLDivElement>;
toast: Toast | null = null;
ngOnInit()
{
this.toast = new Toast(this.toastEl.nativeElement,{});
}
show(){
this.toast!.show();
}
HTML HTML
<button type="button" class="btn btn-primary" id="liveToastBtn"
(click)="show()">Show live toast</button>
<div #myToast role="alert" aria-live="assertive" aria-atomic="true"
class="toast fade" data-bs-autohide="false">
<div class="toast-header">
<img src="..." class="rounded me-2" alt="...">
<strong class="me-auto">Bootstrap</strong>
<small>11 mins ago</small>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-
label="Close"></button>
</div>
<div class="toast-body">
Hello, world! This is a toast message.
</div>
</div>
Add the bootstrap/Types添加引导程序/类型
npm i @types/bootstrap
Then in your component import Toast然后在你的组件中导入 Toast
import {Toast} from 'bootstrap'
Use a template reference for your toast为您的吐司使用模板参考
<div #myToast role="alert" aria-live="assertive" aria-atomic="true" class="toast fade" data-bs-autohide="false">
<div class="toast-header">
<img src="..." class="rounded me-2" alt="...">
<strong class="me-auto">Bootstrap</strong>
<small>11 mins ago</small>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
Hello, world! This is a toast message.
</div>
</div>
And use ViewChild with static true to create the Toast element in ngOnInit并使用 ViewChild 和 static true 在 ngOnInit 中创建 Toast 元素
@ViewChild('myToast',{static:true}) toastEl: any
isClosed(){
return !this.toastEl.nativeElement.classList.contains('show')
}
toast:any
ngOnInit()
{
this.toast=new Toast(this.toastEl.nativeElement,{})
}
Then use toast.show() or toast.hide()然后使用 toast.show() 或 toast.hide()
see the stackblitz看堆栈闪电战
NOTE: You can also use librarys that has toast component, eg ng-bootstrap (I put this because is closer to bootstrap and is "pure" Angular注意:您还可以使用具有 toast 组件的库,例如ng-bootstrap (我之所以这样说是因为它更接近引导程序并且是“纯”Angular
Update We can improve the code using a directive更新我们可以使用指令改进代码
If we create a directive like如果我们创建一个类似的指令
import {Directive,ElementRef} from '@angular/core'
import {Toast} from 'bootstrap'
@Directive({
selector: '.toast', //<--(1)
})
export class ToastDirective {
toast:any;
isClosed(){
return !this.el.nativeElement.classList.contains('show')
}
constructor(private el:ElementRef){
this.toast=new Toast(this.el.nativeElement)
}
toogle()
{
if (this.isClosed())
this.toast.show();
else
this.toast.hide();
}
hide(){
this.toast.hide();
}
show(){
this.toast.show();
}
}
(1) make that the directive is applied to all the div with class="toast". (1) 使该指令适用于所有具有 class="toast" 的 div。
We has all "encapsulated", now if we has a toast我们都“封装”了,现在如果我们举杯
<div #myToast role="alert" aria-live="assertive" aria-atomic="true" class="toast fade" data-bs-autohide="false">
...
</div>
ViewChild is now ViewChild 现在是
@ViewChild('myToast',{static:true,read:ToastDirective}) toast: ToastDirective
And we can do, eg我们可以做,例如
<button class="btn btn-primary" (click)="toast.toogle()">toogle</button>
I create another stackblitz我创建了另一个堆栈闪电战
npm install bootstrap
npm install @types/bootstrap
code...
const Bootstrap = await import('bootstrap');
const Modal = new Bootstrap.Modal(...element..., ...options...);
angular.json
"build": {
...,
"options": {
...,
"allowedCommonJsDependencies": [
"bootstrap"
],
...
},
...
}
Toast try like this像这样吐司
Error npm ERR.错误 npm ERR。 Failed at the client@0.0:0 dev,ssr script - it's not rendering on server as I understand, bootstrap needs DOM.
在 client@0.0:0 dev,ssr 脚本上失败 - 据我了解,它没有在服务器上呈现,引导程序需要 DOM。 but this is just server side.
但这只是服务器端。
The app is crashed: E:\PRACTICE\MYPETPROJECTS\tanechka\client\dist\client\server\main.js:79069 EventHandler.on(document, EVENT_CLICK_DATA_API$7, SELECTOR_DISMISS, Alert.handleDismiss(new Alert())); ^ ReferenceError: document is not defined at E:\PRACTICE\MYPETPROJECTS\tanechka\client\dist\client\server\main.js:79069:19 at E:\PRACTICE\MYPETPROJECTS\tanechka\client\dist\client\server\main.js:78335:28 at Object.SYky (E:\PRACTICE\MYPETPROJECTS\tanechka\client\dist\client\server\main.js:78337:2) at __webpack_require__ (E:\PRACTICE\MYPETPROJECTS\tanechka\client\dist\client\server\main.js:26:30) at Module.Mvz9 (E:\PRACTICE\MYPETPROJECTS\tanechka\client\dist\client\server\main.js:71515:67) at __webpack_require__ (E:\PRACTICE\MYPETPROJECTS\tanechka\client\dist\client\server\main.js:26:30) at Module.PCNd (E:\PRACTICE\MYPETPROJECTS\tanechka\client\dist\client\server\main.js:74232:91) at __webpack_require__ (E:\PRACTICE\MYPETPROJECTS\tanechka\client\dist\client\server\main.js:26:30) at Module.ZAI4 (E:\PRACTICE\MYPETPROJECTS\tanechka\client\dist\client\server\main.js:90421:79) at __webpack_require__ (E:\PRACTICE\MYPETPROJECTS\tanechka\client\dist\client\server\main.js:26:30) A server error has occurred. node exited with 1 code. connect ECONNREFUSED 127.0.0.1:60499 npm ERR. code ELIFECYCLE npm ERR. errno 1 npm ERR: client@0:0:0 dev.ssr. `ng run client:serve-ssr` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the client@0.0.0 dev:ssr script
Single right decision for me was to refuse from using Bootstrap in Angular Universal and replacing it with Angular Material SnackBar and utilities.对我来说,唯一正确的决定是拒绝在 Angular Universal 中使用 Bootstrap,并将其替换为 Angular Material SnackBar 和实用程序。
https://material.angular.io/components/snack-bar/examples https://material.angular.io/components/snack-bar/examples
This line of code这行代码
this.toast = new Toast(this.toastEl.nativeElement,{});
You can also try the following npm package for snackbar.您也可以尝试以下 npm package 用于小吃吧。 This package is having default theme as bootstrap with the Angular Material Implementation.
这个 package 使用 Angular 材料实现作为引导程序的默认主题。
npm install --save @tech-pro/ngx-bootstrap-snackbar
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.