Guide on integrating external libraries with Angular CLI

I've been working on incorporating external libraries into my project, and I've been following the instructions provided here.

While I know it's possible to use CDNs in my index.html, I'm interested in learning how to do it using TypeScript.

Although I successfully added the moment library by referring to the wiki, I encountered difficulties adding both bootstrap and jquery.

system-config.ts

const map: any = {
  'moment': 'vendor/moment/moment.js',
  'jquery': 'vendor/jquery/dist/jquery.js',
  'bootstrap': 'vendor/bootstrap/dist/js/bootstrap.js'
};

/** User packages configuration. */
const packages: any = {
  'moment':{
    format: 'cjs'
  },
  'jquery':{
    format: 'cjs',
    defaultExtension: 'js'
  },
  'bootstrap':{
    format: 'cjs',
    defaultExtension: 'js'
  }
};

angular-cli-build.js

var Angular2App = require('angular-cli/lib/broccoli/angular2-app');

module.exports = function(defaults) {

  return new Angular2App(defaults, {
    vendorNpmFiles: [
      'systemjs/dist/system-polyfills.js',
      'systemjs/dist/system.src.js',
      'zone.js/dist/**/*.+(js|js.map)',
      'es6-shim/es6-shim.js',
      'reflect-metadata/**/*.+(ts|js|js.map)',
      'rxjs/**/*.+(js|js.map)',
      '@angular/**/*.+(js|js.map)',
      'moment/moment.js',
      'jquery/dist/jquery.js',
      'bootstrap/dist/js/bootstrap.js'
    ],
    sassCompiler: {
      includePaths: [
        'src/app/styles'
      ]
    }
  });
};

app.component.ts

import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';
import * as moment from 'moment';
import * as jquery from 'jquery';
// import * as bootstrap from 'bootstrap';

@Component({
  moduleId: module.id,
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css'],
  providers: [],
  directives: [ROUTER_DIRECTIVES]
})

export class AppComponent {
    title = moment().format().toString();
}

If I comment out jquery and bootstrap, the app runs smoothly. However, here is the error message I encounter;

Build error

The Broccoli Plugin: [BroccoliTypeScriptCompiler] failed with:
Error: Typescript found the following errors:
  /home/vadi/dev/orbits/x-orbit/tmp/broccoli_type_script_compiler-input_base_path-p2RtqzmR.tmp/0/src/app/app.component.ts (4, 25): Cannot find module 'jquery'.
    at BroccoliTypeScriptCompiler._doIncrementalBuild (/home/vadi/dev/orbits/x-orbit/node_modules/angular-cli/lib/broccoli/broccoli-typescript.js:120:19)
    at BroccoliTypeScriptCompiler.build (/home/vadi/dev/orbits/x-orbit/node_modules/angular-cli/lib/broccoli/broccoli-typescript.js:43:10)
    at /home/vadi/dev/orbits/x-orbit/node_modules/angular-cli/node_modules/broccoli-caching-writer/index.js:152:21
    at lib$rsvp$$internal$$tryCatch (/home/vadi/dev/orbits/x-orbit/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1036:16)
    at lib$rsvp$$internal$$invokeCallback (/home/vadi/dev/orbits/x-orbit/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1048:17)
    at lib$rsvp$$internal$$publish (/home/vadi/dev/orbits/x-orbit/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1019:11)
    at lib$rsvp$asap$$flush (/home/vadi/dev/orbits/x-orbit/node_modules/angular-cli/node_modules/broccoli-caching-writer/node_modules/rsvp/dist/rsvp.js:1198:9)
    at _combinedTickCallback (internal/process/next_tick.js:67:7)
    at process._tickCallback (internal/process/next_tick.js:98:9)

Therefore, I'd like to ask for recommendations on how to include not only JS files but also CSS files in an angular-cli project.

Your suggestions are highly appreciated.

Answer №1

If you're looking to utilize import in your project with jQuery and bootstrap, you may need to install typings. Alternatively, you can declare it as any in the component/typescript file where it will be used.

To incorporate jQuery, run the following command:

npm install jquery

In your system-config.ts file, add:

 const map: any = {
   'jquery': 'vendor/jquery'
 };

In addition to the vendor npms in your angular-cli-build.js, ensure you also include polyfills:

 vendorNpmFiles: [
      'systemjs/dist/system-polyfills.js',
      'systemjs/dist/system.src.js',
      'zone.js/dist/**/*.+(js|js.map)',
      'es6-shim/es6-shim.js',
      'reflect-metadata/**/*.+(ts|js|js.map)',
      'rxjs/**/*.+(js|js.map)',
      '@angular/**/*.+(js|js.map)',
      'jquery/**/*.js'
    ],
    polyfills:[
       'vendor/jquery/dist/jquery.min.js', 
       'vendor/es6-shim/es6-shim.js',
        'vendor/reflect-metadata/Reflect.js',
        'vendor/systemjs/dist/system.src.js',
        'vendor/zone.js/dist/zone.js', 
    ]

Similarly, repeat this process for integrating bootstrap. When using jQuery throughout the application, be sure to declare it as any instead of importing.

declare var $:any;

Answer №2

Although the above answer is accurate, you might find the information below to be a bit more comprehensive. Sometimes, the previously mentioned solution may not suffice.

In your system-config.ts file, it may be necessary to include meta data for globals with dependencies. Otherwise, errors could arise regarding certain variables like jQuery being undefined.

Consider this example (where "other" is a library that relies on jQuery):

/** User meta config */
const meta: any = {
  'jquery': {
    format: 'global',
    exports: 'jQuery'
  },
  'other': {
    format: 'global',
    exports: 'other',
    deps: ['jquery']
  }
};

To successfully import this library, you may need to implement something similar to the following:

declare var firebase: any;

declare module 'firebase' {
    export = firebase;
}

The aforementioned approach may be considered a workaround, but it could be essential in the short term if typings are not readily accessible. In the provided scenario, the typings for firebase were tailored for SDK version 2.x and thus could not be applied to version 3, necessitating the workaround outlined above.

NOTE: It should be noted that typings for version 3 have been developed by some individuals. It is advisable to always seek out typings for a smoother programming experience, though circumstances may warrant using the workaround described above.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The p-calendar feature is experiencing compatibility issues with Internet Explorer, Edge, and Firefox

While I've had success using primeng p-calendar on Google Chrome, I've encountered an issue where the date-picker does not open upon clicking the text box on other browsers. Below is the snippet of HTML code I utilized: <p-calendar [(ngModel ...

Tips for utilizing angular and express to transmit data via a server and troubleshooting a 404 error

I am currently working on integrating user registration functionality in my frontend using Angular and sending the data to a server (Express). I seem to be facing some issues with the implementation. Does anyone have a solution to this problem? I have set ...

An issue has arisen: It seems that properties of null cannot be accessed, particularly the 'toISOString' property

After upgrading the dependencies in my package.json to their latest versions, I encountered an error while accessing a page that calls this data. Given that the dependencies were outdated by at least 2 years or more, I suspect the issue lies with the updat ...

Angular's table data display feature is unfortunately lacking

Below is a simple HTML code snippet: <div class="dialogs"> <div id="wrapper" > <p>{{createTestingConstant()}}</p> <ng-container *ngFor="let one of contacts"> <p>{{one ...

Registering a function for chart.js plugins that manipulates external data

Is there a way to pass external data to the chart.plugins.register function? I'm struggling because I can't access the necessary context: Chart.plugins.register( { beforeDraw: function (chart) { //implementation } }); I attempted using ...

Utilizing a Variable Value to Invoke a Directive in Angular 2+

I am currently working with Material Angular, and I have the standard button as follows: <button mat-button> x </button> or <button mat-raised-button> x </button> Let's say I have a string variable named 'type', wh ...

Developing Derived Classes in Typescript

I am looking to enhance my service class by creating a subclass where I can define functions with the same name but different implementations. My desired structure is as follows: httpWrapper.get //default is observables. returns observable httpWrapper.pr ...

The method toLowerCase is not found on this data type in TypeScript

I am currently working on creating a filter for autocomplete material. Here is an example of my model: export class Country { country_id: number; name: string; } When calling the web method ws: this.ws.AllCountry().subscribe( ...

Having trouble with data types error in TypeScript while using Next.js?

I am encountering an issue with identifying the data type of the URL that I will be fetching from a REST API. To address this, I have developed a custom hook for usability in my project where I am using Next.js along with TypeScript. Below is the code sni ...

What is the best approach for injecting services (local and API) in Angular 13 based on different environments (local and QA)?

api-local.service.ts import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { LoginRequest } from '../login/login-request'; @Injectable({ providedIn: 'root&ap ...

Is it possible to utilize a function within an Angular [routerLink] to define the query parameter?

When receiving a response from the API without an ID, it presents data fields like url, name, gender, culture, etc. However, I need to create a route to access specific character information using /characters/:id. Since there is no direct ID provided in th ...

Obtain a string of characters from different words

I have been trying to come up with a unique code based on the input provided. Input = "ABC DEF GHI" The generated code would look like, "ADG" (first letter of each word) and if that is taken, then "ABDG" (first two letters o ...

The NGX-Datatable is showing certain numerical values as 'Infinity'

I'm currently investigating why I keep seeing the word 'Infinity' displayed for certain values in my table. For instance, one of the columns is labeled 'Bill To' and has a value of '20E7543' as a string. Despite confirmi ...

The MSAL HTTP_INTERCEPTORS fail to include the request headers seamlessly

Currently, I am in the process of integrating MSAL authentication into my Angular application. The login process at the start is working smoothly with Azure AD. In addition to that, I have included msal_interceptor as a provider in my app.module provider ...

Using react-confetti to create numerous confetti effects simultaneously on a single webpage

I'm looking to showcase multiple confetti effects using the react-confetti library on a single page. However, every attempt to do so in my component seems to only display the confetti effect on the last element, rather than all of them. The canvas fo ...

Angular failing to render data in user interface

Exploring the concept of CRUD Operations, I am attempting to implement basic CRUD operations using Angular for the front end and Web API for the back end. The API is quite straightforward, returning a simple JSON structure as shown below: [ { "stud ...

What is the best way to update my data from the parent component?

Hello, I am trying to update the timestamp value from the parent component. This is my ParentComponent.ts file: public updateTimestamp(){ this.timestamp = new Date(); this.timestamp.setDate(this.timestamp.getDate() - 30); this.timestamp = thi ...

Avoiding Re-renders in an Angular2 Countdown Component

I am facing an issue with my Angular2 master component that includes multiple child components and a standalone countdown component called "clock". The countdown component updates its label every second, causing unnecessary re-rendering of the master compo ...

Error message: The function URL.createObjectURL is not recognized in this context | Issue with Antd charts

Currently, I am working on integrating charts from antd into my TypeScript application. Everything runs smoothly on localhost, but as soon as I push it to GitHub, one of the tests fails: FAIL src/App.test.tsx ● Test suite failed to run TypeError: ...

Running tests on functions that are asynchronous is ineffective

Recently, I made the switch from Java to TypeScript and encountered a challenging problem that has been occupying my time for hours. Here is the schema that I am working with: const userSchema = new Schema({ username : { type: String, required: true }, pa ...