8

I bootstrapped the Angular 2 app using angular-cli. Everything was easy-peasy until I decided to use bootstrap modal. I simply copied the code for opening the modal from our other project that doesn't use angular-cli. I added jquery and bootstrap dependencies to scripts in angular-cli.json file. jQuery is recognised in the project, but when I try to run this.$modalEl.modal(options) inside angular component I get an error that jQuery is not defined.

Actually jQuery is imported into project but as a global $. I've done some digging and apparently bootstrap expects jQuery to be passed into it as a 'jQuery' variable. It doesn't give rat's ass about $.

I could expose jQuery as a variable in webpack.config.js file like we do in other project: (a lot of code omitted for brevity)

var jQueryPlugin = {
  $: 'jquery',
  jquery: 'jquery',
  jQuery: 'jquery'
}

exports.root = root;

exports.plugins = {
  globalLibProvider: new webpack.ProvidePlugin(webpackMerge(jQueryPlugin, {
    svg4everybody: 'svg4everybody/dist/svg4everybody.js'
  }))
}

but angular-cli dev team decided not to let other devs meddle with webpack config files. Thanks guys! Very thoughtful of you.

I've tried importing jQuery directly into Angular component and a bunch of other things mentioned here https://github.com/angular/angular-cli/issues/3202 (adding imports to vendor.ts file and then adding vendor.ts to scripts array in angular-cli.json) but nothing works.

To be honest, I am quite pissed that such a trivial issue like adding jquery dependency to be used with bootstrap in angular-cli is such a minefield.

Have you dealt with similar problem?

codeepic
  • 3,723
  • 7
  • 36
  • 57
  • Why do you say "angular-cli dev team decided not to let other devs meddle with webpack config files"? – K Scandrett Jul 29 '17 at 10:01
  • @KScandrett because angular-cli doesn't expose webpack config file. You configure the app through angular-cli.json. Angular-cli creates webpack config based on it, but there is no straighforward way to edit webpack config file without resorting to some hacks. The team decided to abstract webpack configuration because it's quite difficult for uninitiated. I disagree with their decision, because it makes it harder to configure certain things which you are not able to set in angular-cli.json file. – codeepic Aug 01 '17 at 12:07
  • 1
    Why not just eject it `ng eject` and edit it? – K Scandrett Aug 01 '17 at 12:15
  • That's a fair point. https://github.com/angular/angular-cli/wiki/eject Can you still use angular-cli generators after you ejected the app? – codeepic Aug 01 '17 at 12:17
  • I haven't tried. If the generators don't work you might be able to do https://github.com/aspnet/JavaScriptServices/issues/828#issuecomment-290728688. – K Scandrett Aug 02 '17 at 01:05

3 Answers3

4

Step One

npm install jssha --save [using jssha for this demo]
It it is your own custom file place it in the scripts array of angular-cli.json skip this step 1

Step two

Add the jssha scripts file in .angular-cli.json file
"scripts": [ "../node_modules/jssha/src/sha.js" ]
Step three Adding a var in component to be used as a global variable

//using external js modules in Angular Component
declare var jsSHA: any; // place this above the component decorator
shaObj:any;
hash:string;
this.shaObj = new jsSHA("SHA-512", "TEXT");
this.shaObj.update("This is a Test");
this.hash = this.shaObj.getHash("HEX")

Take a look @ this link. It has a working example and a question for the same with typings and without it. I have used bootstrap and jquery with Angular in that project, you can check the repo too.

In your case you need to add the jquery files

like this in your angular-cli.json

  "styles": [
    "../node_modules/bootstrap-v4-dev/dist/css/bootstrap.min.css",
    "styles.css"
  ],
  "scripts": [
    "../node_modules/jquery/dist/jquery.js",
    "../node_modules/tether/dist/js/tether.min.js",
    "../node_modules/bootstrap-v4-dev/dist/js/bootstrap.min.js"

and then declare in component.declare var $: any;

This should work.

UPDATE

I went on to create a modal of bootstrap using just jquery in Angular using the steps i mentioned.

It works Check this gh page link - LINK.

and if you want to check the source code for the same check LINK.

The answer i posted came from this link this is my page on Angular LINK

Rahul Singh
  • 19,030
  • 11
  • 64
  • 86
  • But why do I need to add `jssha` to my project? – codeepic Aug 02 '17 at 12:44
  • that's a demo for your case it will be jquery, i mentioned this `[using jssha for this demo]` – Rahul Singh Aug 02 '17 at 12:44
  • Well in that case your answer doesn't fix my problem, I have already added jquery dependency to scripts array in angular.cli.json file. The problem seems to be that jQuery exposes `$` as a global variable and bootstrap-sass expects `jQuery` not `$` sign. – codeepic Aug 02 '17 at 12:47
  • you also need to declare that varaible in the component like | `declare var $: any;` – Rahul Singh Aug 02 '17 at 12:48
  • `declare var $: any;` that's provided I get the error in the component, but that's not the case. I get 'jQuery is not defined' in bootstrap modal file. – codeepic Aug 02 '17 at 12:48
  • have you defined bootstrap js in scripts file ? – Rahul Singh Aug 02 '17 at 12:50
  • Yes. I did. Otherwise I would be getting an error like `thee is no method on $modalEl` when trying to run this code `this.$modalEl.on('shown.bs.modal', () => this.onOpen());` – codeepic Aug 02 '17 at 12:54
  • i will try to add a modal and let you know – Rahul Singh Aug 02 '17 at 12:57
  • Don't worry about it. I used `ng-bootstrap` and it's working fine. To hell with jQuery and bootstrap-sass. – codeepic Aug 02 '17 at 12:58
  • its pretty easy i have used it my web page too and it works like a charm i hate using modules for everything – Rahul Singh Aug 02 '17 at 12:58
  • I know how to create modal just with Angular, but that was not the point of my question. If I am going to use bootstrap for layout and different components I may just as well use its modal. – codeepic Aug 02 '17 at 12:59
  • Thanks, your app is working with angular-cli, jquery and bootstrap, although I was using bootstrap-sass. I wonder whether it makes a difference. You really put a lot of effort into helping me. Thanks. I wish I could give you the bounty but I already gave it to Matthew after I implemented ng-bootstrap as he recommended. – codeepic Aug 02 '17 at 17:15
  • 1
    @codepic no issue i didn't do it for bounty just that it works needed to share the information – Rahul Singh Aug 02 '17 at 17:16
1

I haven't specifically used Bootstrap with Angular 2, but I have with Angular 1 and the situation is the same in that the regular version of Bootstrap is designed to work with jQuery and is not built with Angular in mind. You can of course install jQuery but the Javascript may not work as expected in the context of Angular.

The easiest solution is to use a version that is built with Angular in mind, and I believe ng-bootstrap is the most prominent of these. I haven't used it myself, but I have used angular-ui-bootstrap for Angular 1 and this appears to be an Angular 2 counterpart to the same project.

Alternatively, you can wrap it in a directive yourself, but I would avoid doing so if you can get ng-bootstrap to do what you want since it will be much more work.

Matthew Daly
  • 9,212
  • 2
  • 42
  • 83
  • 1
    He would have to upgrade to Angular 4 to use [ng-bootstrap](https://ng-bootstrap.github.io/#/home). Once that has been done, their modal component works well. – ConnorsFan Jul 29 '17 at 15:39
  • @Matthew Daly This doesn't answer my question perfectly but nevertheless it's the best solution. Ng-bootstrap is quite elegant and doesn't rely on jQuery. So I replaced bootstrap-sass and jQuery for ng-bootstrap in my dependencies. – codeepic Aug 02 '17 at 13:04
  • 1
    Glad it resolves your issue. Obviously you *can* create your own directive to wrap it if need be (and sometimes this is the only solution, especially if you're working with something relatively obscure), but for something as common as Bootstrap there's nearly always an existing solution, and if you've going to need more than one component you're making a lot of work for yourself if you choose to do it yourself. – Matthew Daly Aug 02 '17 at 19:21
1

You can use the command ng eject to have Angular CLI generate the webpack.config file.

Then expose jQuery as a variable as you've done before.

K Scandrett
  • 16,390
  • 4
  • 40
  • 65