带 Angular 的引导程序“错误:$(...).collapse() 不是函数”

Posted

技术标签:

【中文标题】带 Angular 的引导程序“错误:$(...).collapse() 不是函数”【英文标题】:Bootstrap w/ Angular "Error: $(...).collapse() is not a function" 【发布时间】:2018-09-24 01:39:00 【问题描述】:

我是 Bootstrap 的新手,并尝试在用户单击链接时从 Angular 控制器中的 javascript 激活 .collapse() 函数。当单击其中一个链接时,这应该会关闭可折叠导航栏(因为路由由 Angular 控制,不会导致页面刷新)。

以下错误显示:

ERROR TypeError: $(...).collapse is not a function
    at htmlAnchorElement.<anonymous> (header.component.ts:18)
    at HTMLAnchorElement.dispatch (jquery.js:5183)
    at HTMLAnchorElement.elemData.handle (jquery.js:4991)
    at ZoneDelegate.webpackJsonp../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
    at Object.onInvokeTask (core.js:4740)
    at ZoneDelegate.webpackJsonp../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420)
    at Zone.webpackJsonp../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188)
    at ZoneTask.webpackJsonp../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (zone.js:496)
    at invokeTask (zone.js:1540)
    at HTMLAnchorElement.globalZoneAwareCallback (zone.js:1577)

HTML模板的相关部分:

<div class='collapse navbar-collapse' id='mainNavbar'>
  <div class='navbar-nav'>
    <div [ngClass]=' "nav-item": true, active: pageTitle === "Home" '>
      <a class='nav-link' routerLink='/'>Home</a>
    </div>
    <div [ngClass]=' "nav-item": true, active: pageTitle === "Request" '>
      <a class='nav-link' routerLink='/request'>Request</a>
    </div>
    <div [ngClass]=' "nav-item": true, active: pageTitle === "Volunteer" '>
      <a class='nav-link' routerLink='/volunteer'>Volunteer</a>
    </div>
    <div [ngClass]=' "nav-item": true, active: pageTitle === "About" '>
      <a class='nav-link' routerLink='/about'>About</a>
    </div>
  </div>
</div>

控制器的相关部分:

// importing jquery from npm module
import * as $ from 'jquery';

// inside the controller class
ngOnInit() 
  $('.nav-link').click(() => $('.collapse').collapse('toggle'));

包含的脚本(.angular-cli.json):

"scripts": [
  "../node_modules/jquery/dist/jquery.min.js",
  "../node_modules/popper.js/dist/umd/popper.min.js",
  "../node_modules/bootstrap/dist/js/bootstrap.min.js"
]

我见过多个这样的问题,但几乎总是答案说要确保 jQuery 在 Bootstrap 之前包含,并且 Bootstrap 不包含两次。这里也不是。

其他 jQuery 功能(正常折叠功能)工作正常。如果我尝试在下拉菜单上使用 .dropdown() 函数,也会出现同样的错误。

这里有什么问题?


如果您需要:Angular 5、Bootstrap v4.0.0(npm 模块)、jQuery v3.3.1(npm 模块)

【问题讨论】:

嗯。为什么这立即被否决?我是不是不够彻底? 添加js文件后是否重启ng serve @David 是的,我做到了。 如果你尝试declare let $: any而不是你的导入呢? 我假设如果你将jquery 导入为$,这意味着$ 将只包含jquery 包中定义的代码,而不包含bootstrap 声明的附加插件。如果你使用declare let ...,那么$代表普通的jQuery函数加上额外的插件 【参考方案1】:

这对我有用

import * as $ from 'jquery';
declare var $:any;

在 angular.json 中

"styles": [
          "src/styles.css",
          "node_modules/bootstrap3/dist/css/bootstrap.min.css",
          "node_modules/ngx-toastr/toastr.css"
        ],
"scripts": [
          "node_modules/jquery/dist/jquery.min.js",
          "node_modules/bootstrap3/dist/js/bootstrap.js"
        ]

现在您可以在 Angular 7 中使用折叠

 $(".panel-collapse").collapse("hide");

【讨论】:

【参考方案2】:

用途:

declare let $ : any;

代替:

import * as $ from 'jquery';

作为一种解决方法,您可以使用:

$('#yourId').removeClass('show');

(对于其他用户)

确保您在angular.json 上设置了问题:

"scripts": [
    "node_modules/jquery/dist/jquery.min.js",
    "node_modules/popper.js/dist/umd/popper.min.js",
    "node_modules/bootstrap/dist/js/bootstrap.min.js"
 ]

【讨论】:

【参考方案3】:

您需要使用declare let $ : any; 而不是您的导入

我假设如果你使用

import jquery as $ from 'jquery';

那么这意味着 $ 将仅包含 jquery 包中定义的代码,而不包含 bootstrap(或任何其他 jquery 插件)声明的附加插件。

如果你使用

declare let $ : any;

那么 $ 代表普通的 jQuery 函数加上其他库添加的附加插件(collapse,dropdown,...)

如果不想使用any,需要显式调用一些插件方法,则需要扩展jQuery的接口

interface JQuery 

    carousel(options : any);


declare let $: JQuery;

注意如果可以避免,则应避免在原生 Angular 方法可用时使用 jquery 或 jquery 插件

对于 boostrap,就像提到的 ConnorsFan 一样,您可以使用 ng-bootstrap 作为替代品。它需要 bootstrap 的 CSS 文件,但动态组件已经用原生 Angular 重写,不需要 jQuery

【讨论】:

完美的解释。完美运行。【参考方案4】:

当您在 Angular 应用程序中时,不需要 jQuery。您可以改用局部变量。在this stackblitz 中实际上有一个很好的例子来说明如何做到这一点

【讨论】:

我知道没有必要使用 jQuery,但 Bootstrap 已经需要加载 jQuery。我想我还不如使用 jQuery 便利函数而不是自己在 Angular 中实现它。 当将 bootstrap 引入 Angular 应用程序时,最好使用 ngx-bootstrap 或 ng-bootstrap 而不是原生的 jQuery 功能。从长远来看,使用 jQuery 会给你带来一些问题,因为它会让你脱离 Angular 的可见性,并且有可能导致意想不到的副作用。 我在我的所有 Angular 项目中都使用 bootstrap,我通过 SCSS 在应用程序的主样式表中提取样式,从那里我使用 ngx-bootstrap 来提供我的 bootstrap 组件的功能。 好的,谢谢。以后我会考虑到这一点。【参考方案5】:

经过更多研究,我发现this Stack Overflow answer 建议添加以下行(替换import * as $ from 'jquery'):

declare let $: any;

不幸的是,我不明白这意味着什么或它是如何工作的,但它为我解决了问题。希望这对某人有所帮助。

【讨论】:

你自己回答很快,如果你想把它添加到你自己的答案中,我已经为你准备了这个样本。 stackblitz.com/edit/angular-hhf14h?file=app%2Fapp.component.ts @Yanis-git 感谢您的示例! 不幸的是我不能,在我的示例中的第二个按钮上,我激活了真正的切换,只是打开下拉菜单然后什么都没有。

以上是关于带 Angular 的引导程序“错误:$(...).collapse() 不是函数”的主要内容,如果未能解决你的问题,请参考以下文章

Angular-universal 出现错误:您必须传入 NgModule 或 NgModuleFactory 才能被引导

我在 Angular 8 中安装了引导程序但无法正常工作。为啥?

Angular2 beta14 Typescript routerLink绑定错误[重复]

angular-cli 如何添加 sass 和/或引导程序?

Yeoman 构建的 Angular 应用程序未将引导字体部署到 Heroku

Angular - Spring Boot - Keycloak - 401错误