3

I'm currently developing an Angular4 application and I want to import some javascript libraries but just for a single component. Currently I can easily import this libraries by defining their paths inside .angular-cli.json like that:

{
   "scripts": [
      "../node_modules/jquery/dist/jquery.min.js",
      "../node_modules/jqueryui/jquery-ui.js",
      "../src/assets/js/jquery/cometd/org-cometd.js",
      "../src/assets/js/jquery/cometd/jquery.cometd.js",
   ],
   ...
}

However, the mentioned scripts will be imported for all the application. Is there a way to import them just for a specific component ? I've tried to import them inside the component like shown below but without success.

import { Component, OnInit, ViewEncapsulation, Inject } from '@angular/core';
...
import "../../../../../node_modules/jquery/dist/jquery.min.js";
import "../../../../../node_modules/jqueryui/jquery-ui.js";
import "../../../../assets/js/jquery/cometd/org-cometd.js";
import "../../../../assets/js/jquery/cometd/jquery.cometd.js";

@Component({
   selector: '...',
   templateUrl: '...',
   styleUrls: '...',
   encapsulation: ViewEncapsulation.None
})

export class MyComponent implements OnInit {
   ...
}

[UPDATE] - I forgot to mention that I am currently using the ViewEncapsulation.None to be able to apply the styles from some css files into the component. Not sure if this detail can be related with the issue.

2
  • you can add them to document by using their path from assets folder or cdn document.head.appendChild(...path); Commented Jan 9, 2018 at 17:18
  • thanks, it seems to work at least for some of the libraries... Commented Jan 9, 2018 at 18:22

3 Answers 3

2

Things like jQuery and bootstrap are global and will be available to the application. But, it is good practice to make them injectable and thus referable from single components.

First install jQuery

npm install --save jquery
npm install -D @types/jquery

Second make an injection module

import { NgModule } from '@angular/core';
import { InjectionToken } from '@angular/core';
import * as jquery from 'jquery';

export const JQUERY = new InjectionToken<jquery>('jQuery');

export function _jquery(): jquery {
  return jquery;
}

@NgModule({
  providers: [{
    provide: JQUERY,
    useFactory: _jquery
  }]
})
export class JqueryTokenModule { }

Third, in your module:

providers: [{provide: JQUERY, useValue: _jquery}]

Finally, inject it into your component

constructor(@Inject(JQUERY) private $) {
  // use `this.$` which is jQuery
}
Sign up to request clarification or add additional context in comments.

Comments

1

You can import them inside component using import. For example for jQuery it will be

import * as $ from 'jquery';

which means "import all as '$' (and use it as '$' further) from 'jquery' library", and you don't really need to include another import to .angular.cli.json. It works fine for Angular 5 (I have tested it right now), I think, it should work for 2 and 4 versions too. To ensure that it works, you can write console.log($) in ngOnInit block (for example).

6 Comments

Using this I still get the console error scripts.bundle.js:3186 Uncaught ReferenceError: jQuery is not defined. I've installed jquery via npm install --save jquery and removed the reference to the script inside the angular-cli.json
It's a little strange, because I have generated new Angular 5 project and imported jQuery and it works fine without additional config =/
I forgot to mention that I am currently using the ViewEncapsulation.None. I'm not sure if this detail could be related...
@DavidR, I think it shouldn't affect.
@DavidR try using lowercase in "Uncaught ReferenceError: jQuery is not defined"
|
0

You can do it simply by fetching the src js and importing it in your component.

Here is an example from a leaflet application I did :

package.json :

"leaflet.markercluster": "^1.1.0",
"leaflet-draw": "^0.4.12",

random1.component.ts : with markercluster library example

declare const L: any;
import 'leaflet.markercluster';

export function initMarkerCluster(map: L.Map, mapService: LeafletService) {
  // Set the ClusterMarkerLayer
  const cluster = L.markerClusterGroup();
  ...
}

random2.component.ts : with leaflet.draw library example

declare const L: any;
import 'leaflet-draw/dist/leaflet.draw-src';

export function drawPlugin(map: L.Map, mapService: LeafletService) {
  const drawnItems: L.FeatureGroup = L.featureGroup().addTo(map);
  const drawControl = initDrawControl(drawnItems);
  map.addControl(drawControl);
  ...
}

Note : In these leaflet libraries there was the namespace L for Leaflet so I declared a global variable, but you shouldn't need that.

4 Comments

thanks for your answer ;) what if the js files I want to import are custom files and not from 3rd party ?
It shouldn't matter and should work the same. Here my imports were targetting the leaflet libraries from node_modules, so you just need to change the import path. Once it is imported in the component, it is used at runtime. If the file doesn't exist, it will tell you that the import is not correct. You can try calling a method from your custom file, it should work the same. Check how those files are made to ensure that it will be working the same way though.
I have lots of custom js files to import, do I really need to declare a const for each one ? These files have mostly global vars and functions declared...
No, as I said in the final note, this was specific from my leaflet libraries that had everything encapsulated in the namespace L. If you only have functions or whatever from your JS files, just importing them should be enough.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.